#include "UserAccountManager.h"

#include <core/Events.h>
#include <core/FileSys.h>
#include <core/Utility.h>
#include <core/sharedata/login_data.h>
#include <core/thirdparty/json/json.h>
#include <core/time/system_time.h>
#include <qbkernel/include/qb_base.h>
#include <qbprotocol/include/rdProto.h>
#include <qbprotocol/include/ssCmnDefine.h>
#include <qbtools/message/MessagePoster.h>
#include <time.h>

#include "QBFlags.h"
#include "ServerTimeMgr.h"
#include "UamMsgProcess.h"
#ifdef _MSC_VER
#include <windows.h>
#else
#include <arpa/inet.h>
#endif

#define SSM_METRICS  //

#define MAX_PATH 260

// 拉点详情///
//   bool CLevelItemList::Insert(char* brokerID,char* pCompanyType,xLevelItem_c
//   xItem)
//   {
//       CLevelItem levelItem(brokerID,pCompanyType,xItem);
//       m_List.push_back(levelItem);
//       return true;
//   }

static CLevelItemList LevelListNull;
int SSUserAccountManager::GetBussinessState(int statusC, int statusT,
                                            int statusB) {
  // statusC 公司状态，0未申请，1白名单，-1黑名单
  // statusT 申请状态，0未申请，1已申请
  // statusB 审核状态，0未审核，1已审核，2已拒绝，3已停用，-1黑名单
  if (statusC == -1) {  // 公司黑名单
    return typeNull;
  } else {
    if (statusB == -1)  // 个人黑名单
    {
      return typeNull;
    } else {
      if (statusT == 0)  // 未申请
      {
        return typeApply;
      } else  // 已申请
      {
        if (statusB == 1)  // 已审核
        {
          return typeApplyPass;
        } else if (statusB == 2)  // 已拒绝
        {
          return typeApplyNPass;
        } else if (statusB == 3)  // 已停用
        {
          return typeStop;
        } else  // 未审核
        {
          if (statusC == 1)  // 公司白名单
          {
            return typeApplyPass;
          } else  // 待审核
          {
            return typeApplying;
          }
        }
      }
    }
  }
  return typeNull;
}
bool SSUserAccountManager::GetBussinessNoPass(int statusC, int statusT,
                                              int statusB) {
  if (statusC == -1 ||
      (statusC != -1 && (statusB == -1 || statusB == 2 || statusB == 3)))
    return true;
  return false;
}

bool CLevelItemList::Insert(const CLevelItem& cpLevelItem) {
  m_List.push_back(cpLevelItem);
  return true;
}
bool CLevelItemList::GetLevelItem(const char* brokerID, const char* pszKey,
                                  CLevelItem& stItem) {
  if (brokerID == nullptr || pszKey == nullptr) return false;

  CLevelItem levelItem;
  std::list<CLevelItem>::iterator itor;

  FIELDCOPY(levelItem.m_BrokerID, brokerID);
  FIELDCOPY(levelItem.m_ItemKey, pszKey);
  itor = find(m_List.begin(), m_List.end(), levelItem);
  if (itor == m_List.end()) return false;
  stItem = *itor;
  return true;
}

int CBrokerUnit::GetDefaultContactID(const char* skey) const {
  if (!skey || skey[0] == '\0') return -1;
  auto it = m_DefaultContact.find(skey);
  if (it == m_DefaultContact.end()) return -1;
  return it->second;
}

const char* CBrokerUnit::GetDefaultContactQQ(const char* skey) const {
  int cid = GetDefaultContactID(skey);
  if (cid < 0) return nullptr;
  for (auto it = m_ContactList.begin(); it != m_ContactList.end(); it++) {
    if (it->m_ID == cid) {
      if (strcmp(it->m_Dept, skey) == 0) {
        if (strlen(it->m_QQEnterprise))
          return it->m_QQEnterprise;
        else
          return it->m_QQ;
      }
      break;
    }
  }
  return nullptr;
}

//
SSUserAccountManager& SSUserAccountManager::instance() {
  static SSUserAccountManager gUAM;
  return gUAM;
}

void SSUserAccountManager::init() {
#define REG_REQ(REQ) \
  qb::qbBase::getMessageBond()->RegisterMsgProcessor(REQ, this)
  REG_REQ(E_FID_QB_USER_PERMISSION_REQ);
  REG_REQ(E_FID_QB_CDC_AUTHORITY_REQ_V2);
  REG_REQ(E_FID_QB_CSI_AUTHORITY_REQ);
  REG_REQ(E_FID_QB_ALL_CMPY_QRY);
  REG_REQ(E_FID_QB_FLAGS_REQ);
  REG_REQ(E_FID_QB_GLOBAL_SWITCH);
  REG_REQ(E_FID_QB_QUERY_NEW_UERINFO_REQ);
  REG_REQ(E_FID_QB_USEPROTOCAL_QUERY_REQ);
  REG_REQ(E_FID_QB_USER_MEMBER_INFO_REQ);
  REG_REQ(E_FID_QB_AUTHORITY_QUERY_NEW_REQ);
  REG_REQ(E_FID_QB_MOBILE_VERIFY_INFO);
  REG_REQ(E_FID_QB_CONDITION_GRUOP_REQ_NEW);

  qb::qbBase::getMessageProcess()->RegisterMsgProcessorOnThread(E_FID_SYS_TIME,
                                                                this);
  qb::qbBase::getMessageProcess()->RegisterMsgProcessorOnThread(E_FID_SIGNAL,
                                                                this);

  if (m_sysTimerId == 0) m_sysTimerId = startTimer(1000 * 60);
}

STDMETHODIMP_(void)
SSUserAccountManager::OnResponse(THIS_ int32_t funcId,
                                 const qb::SSAckMsg& msg) {
  if (!msg.m_pRet) return;

  if (E_FID_QB_USER_PERMISSION_REQ == funcId) {
    const xQBUserPermissionAck_c* pdata = (xQBUserPermissionAck_c*)msg.m_pRet;
    SSUserAccountManager& uam = SSUserAccountManager::instance();
    if (strcmp(uam.GetUserInfo().m_UserId, pdata->m_UserId) != 0 ||
        strcmp(uam.GetUserInfo().m_CompanyId, pdata->m_CompanyId) != 0)
      return;

    SSUserPermission& up = SSUserAccountManager::instance().GetPermission();
    for (auto it = pdata->m_List.begin(); it != pdata->m_List.end(); it++) {
      log_debug("Permission | Code = %s, Value = %s", it->m_Index, it->m_Value);
      up.SetValue(it->m_Index, it->m_Value);
    }
    uam.ResetExchangeInit();  // 重置交易所权限存储初始化
  } else if (E_FID_QB_CDC_AUTHORITY_REQ_V2 == funcId) {
    const xCDCAuthorityAct_c* pAuthData = (xCDCAuthorityAct_c*)msg.m_pRet;
    SSUserAccountManager::instance().SetCDCAutority(pAuthData);
  } else if (E_FID_QB_CSI_AUTHORITY_REQ == funcId) {
    const xCSIAuthorityAct_c* pAuthData = (xCSIAuthorityAct_c*)msg.m_pRet;
    SSUserAccountManager::instance().SetCSIAuthorityFlag(pAuthData->m_Allowed);
  } else if (E_FID_QB_ALL_CMPY_QRY == funcId) {
    const xQBTradeCmpyInfoListAck_c* plst =
        ((xQBTradeCmpyInfoListAck_c*)(msg.m_pRet));
    SetBroker(plst);
    if (!msg.m_pRet) return;
    const std::list<xQBTradeCmpContact_c>& contact_info =
        ((xQBTradeCmpyInfoListAck_c*)msg.m_pRet)->m_ContactList;
    // clear previous contact info

    CBrokerList::Writer writer = GetBroker();
    writer.ClearAllContactList();

    // add contact info by company_id
    for (auto cit = contact_info.begin(); cit != contact_info.end(); ++cit) {
      writer.AddContact(cit->m_CompanyId, *cit);
    }

    requestUserAuthority();
  } else if (E_FID_QB_FLAGS_REQ == funcId) {
    const xQBFlagsAck_c* ack = static_cast<xQBFlagsAck_c*>(msg.m_pRet);
    CQBFlags::instance().Update(ack);
    SSUserAccountManager::instance().SetBrokerDefaultContact(ack);
  } else if (E_FID_QB_GLOBAL_SWITCH == funcId) {
    const xQBGlobalSwitchAck_t* ack =
        static_cast<xQBGlobalSwitchAck_t*>(msg.m_pRet);
    SSUserAccountManager::instance().SetSystemVariabls(ack->m_Flags);
  } else if (E_FID_QB_QUERY_NEW_UERINFO_REQ == funcId ||
             E_FID_QB_USEPROTOCAL_QUERY_REQ == funcId) {
    SetUserInfo(msg.m_pRet, funcId);
    if (E_FID_QB_QUERY_NEW_UERINFO_REQ == funcId) {
      requestUserProtocol();
      requestUserMemInfo();
      // RequestCommonMenu();
    }
  } else if (E_FID_QB_USER_MEMBER_INFO_REQ == funcId) {
    const xUserMemberInfoAck_c* pdata =
        static_cast<xUserMemberInfoAck_c*>(msg.m_pRet);
    if (strcmp(SSUserAccountManager::instance().GetUserInfo().m_UserId,
               pdata->m_UserId) != 0 ||
        strcmp(SSUserAccountManager::instance().GetUserInfo().m_CompanyId,
               pdata->m_CompanyId) != 0)
      return;  // 当用户Id不对应时，不更新数据
    SSUserAccountManager::instance().GetUserMemberInfo().UpdateMemberInfo(
        pdata, ServerTimeMgr::instance().serverTime());
  } else if (E_FID_QB_AUTHORITY_QUERY_NEW_REQ == funcId) {
    const xQBAuthorityQueryAck_c* pdata = (xQBAuthorityQueryAck_c*)msg.m_pRet;
    log_debug("%d, m_BusinessList.size = %d,m_ItemList.size = %d", funcId,
              pdata->m_BusinessList.size(), pdata->m_ItemList.size());
    const size_t nSize = pdata->m_BusinessList.size();
    const size_t nItemSize = pdata->m_ItemList.size();
    if (nSize == 0 && nItemSize == 0) return;

    SSUserAccountManager& uam = SSUserAccountManager::instance();
    for (auto it = pdata->m_BusinessList.begin();
         it != pdata->m_BusinessList.end(); ++it) {
      log_debug("m_CompanyType = %s, BusinessCode = %s, m_BrokerID = %s",
                it->m_CompanyType, it->m_BusinessCode, it->m_BrokerID);
      log_debug("\tm_BrokerName = %s, m_AllowName = %s, m_AllowNameEn = %s",
                it->m_BrokerName, it->m_AllowName, it->m_AllowNameEn);
      log_debug("\tm_Status_C:%d T:%d B:%d", it->m_Status_C, it->m_Status_T,
                it->m_Status_B);

      CBrokerList::Writer writer = uam.GetBroker();
      int nBrokerID = atoi(it->m_BrokerID);
      bool isBroker =
          strlen(it->m_BrokerID) < 3 && CBrokerList::IsValidBroker(nBrokerID);
      if (isBroker) {
        writer.AddBusiness(nBrokerID, *it);
      }

      if (strcmp(it->m_BusinessCode, "BOND") == 0 && isBroker) {
        bool bEnable = (SSUserAccountManager::GetBussinessState(
                            it->m_Status_C, it->m_Status_T, it->m_Status_B) ==
                        SSUserAccountManager::typeApplyPass);
        writer.SetBONDEnableFlag(nBrokerID, bEnable);
        if (bEnable) writer.SetBondBusinessLevel(it->m_BusinessLevel);
      } else if (strcmp(it->m_BusinessCode, "NCD") == 0 && isBroker) {
        bool bEnable = (SSUserAccountManager::GetBussinessState(
                            it->m_Status_C, it->m_Status_T, it->m_Status_B) ==
                        SSUserAccountManager::typeApplyPass);
        writer.SetNCDEnableFlag(nBrokerID, bEnable);
      } else if (strcmp(it->m_BusinessCode, "IRS") == 0 && isBroker) {
        writer.SetIRSEnableFlag(
            nBrokerID, SSUserAccountManager::GetBussinessState(
                           it->m_Status_C, it->m_Status_T, it->m_Status_B) ==
                           SSUserAccountManager::typeApplyPass);
      }

      {
        CQuoteBankList& QuoteBankList = uam.GetQuoteBankList();
        auto itMap = QuoteBankList.m_mapBank.find(std::string(it->m_BrokerID));
        if (itMap == QuoteBankList.m_mapBank.end()) {
          QuoteBankList.m_mapBank[std::string(it->m_BrokerID)]
              .m_BusinessList.push_back(*it);
        } else {
          bool bexist = false;
          auto itList = itMap->second.m_BusinessList.begin();
          for (; itList != itMap->second.m_BusinessList.end(); itList++) {
            if (strcmp(itList->m_BusinessCode, it->m_BusinessCode) == 0) {
              *itList = *it;
              bexist = true;
            }
          }
          if (!bexist) itMap->second.m_BusinessList.push_back(*it);
        }
      }
    }

    auto levelItor = pdata->m_ItemList.begin();
    for (; levelItor != pdata->m_ItemList.end(); levelItor++) {
      const CBrokerList& brokerlist = uam.GetReadonlyBroker();
      for (auto bit = brokerlist.GetBrokerMap().begin();
           bit != brokerlist.GetBrokerMap().end(); bit++) {
        CBrokerUnit stUnit = bit->second;
        std::list<xQBAuthorityBusiness_c>::iterator xqbAuthItor;
        xqbAuthItor =
            find_if(stUnit.m_BusinessList.begin(), stUnit.m_BusinessList.end(),
                    AutBusi_Compare(levelItor->m_BusinessLevel));
        if (xqbAuthItor != stUnit.m_BusinessList.end()) {
          CLevelItem cpLevelItem(xqbAuthItor->m_BrokerID,
                                 xqbAuthItor->m_CompanyType,
                                 xqbAuthItor->m_BusinessCode, *levelItor);
          uam.InsertLevelItem(cpLevelItem);
          continue;
        }
      }

      CQuoteBankList& QuoteBankList = uam.GetQuoteBankList();
      //                QuoteBankList.m_mapBank[string(it->m_BrokerID)].m_BusinessList.push_back(*it);
      for (auto qbuItor = QuoteBankList.m_mapBank.begin();
           qbuItor != QuoteBankList.m_mapBank.end(); ++qbuItor) {
        CQuoteBankUnit stUnit = qbuItor->second;
        std::list<xQBAuthorityBusiness_c>::iterator xqbAuthItor;
        xqbAuthItor =
            find_if(stUnit.m_BusinessList.begin(), stUnit.m_BusinessList.end(),
                    AutBusi_Compare(levelItor->m_BusinessLevel));
        if (xqbAuthItor != stUnit.m_BusinessList.end()) {
          CLevelItem cpLevelItem(xqbAuthItor->m_BrokerID,
                                 xqbAuthItor->m_CompanyType,
                                 xqbAuthItor->m_BusinessCode, *levelItor);
          uam.InsertLevelItem(cpLevelItem);
        }
      }
    }
    if (msg.m_IsReceving == 0) {
      uam.SetAuthListFlag();
      uam.InitIDCPermission();
      uam.UpdatePrimaryAuth();
    }
  } else if (E_FID_QB_MOBILE_VERIFY_INFO == funcId) {
    const xQBMobileVerifyInfoAck_c* pdata =
        (xQBMobileVerifyInfoAck_c*)msg.m_pRet;
    GetMobileConfirm().SetParams(pdata);
  }
}

void SSUserAccountManager::OnResponse(THIS_ int32_t msgtype,
                                      qb::ProcessMessage msp) {
  if (msgtype == E_FID_SYS_TIME && msp.retCode() == qb::E_RC_OK) {
    xSysTime_t xBody;
    memcpy(&xBody, msp.getBuff() + sizeof(qb::xMsgHeadAck_t), sizeof(xBody));
    xBody.time = ntohl(xBody.time);
    ServerTimeMgr::instance().setServerTime(xBody.time);
  } else if (msgtype == E_FID_SIGNAL) {
    xMarketSignalInfo_t xBody;
    memset(&xBody, 0, sizeof(xBody));
    memcpy(&xBody, msp.getBuff() + sizeof(qb::xMsgHeadAck_t), sizeof(xBody));
    xBody.curtime = ntohl((u_long)xBody.curtime);
    xBody.market = ntohl(xBody.market);
    xBody.marketStatus = ntohl(xBody.marketStatus);
    emit recvSignal(xBody);
  }
}

void SSUserAccountManager::timerEvent(QTimerEvent* event) {
  if (event->timerId() == m_sysTimerId) requestSystime();
}

SSUserAccountManager::SSUserAccountManager(void)
    : m_bGotBrokerList(false),
      m_bGotAuthList(false),
      m_bQuoteAuth(false),
      m_bBrokerMobileOnline(false),
      m_bUseProtocol(true),
      m_Menu("menu"),
      m_MenuRelation("menuRelation"),
      m_MenuCommont("menuComment") {
  m_nComsAuthority = 0;
  m_CDCAuthorityOld = 0;
  m_CDCAuthoriryInit = true;
  m_hasAnyCDCAuth = false;
  memset(m_sComsAccessID, 0, sizeof(m_sComsAccessID));
  if (0) {
    xCDCAuthorityUnit unit;
    unit.m_AuthValue = 1;
    FIELDCOPYN(unit.m_AuthName, sizeof(unit.m_AuthName), "中债托管券 - 当年");
    m_CDCAuthority.insert(std::make_pair(unit.m_AuthValue, unit));
    unit.m_AuthValue = 2;
    FIELDCOPYN(unit.m_AuthName, sizeof(unit.m_AuthName), "短融中票 - 当年");
    m_CDCAuthority.insert(std::make_pair(unit.m_AuthValue, unit));
    unit.m_AuthValue = 3;
    FIELDCOPYN(unit.m_AuthName, sizeof(unit.m_AuthName),
               "PPN和其他融资工具 - 当年");
    m_CDCAuthority.insert(std::make_pair(unit.m_AuthValue, unit));
    unit.m_AuthValue = 4;
    FIELDCOPYN(unit.m_AuthName, sizeof(unit.m_AuthName), "同业存单 - 当年");
    m_CDCAuthority.insert(std::make_pair(unit.m_AuthValue, unit));
    unit.m_AuthValue = 5;
    FIELDCOPYN(unit.m_AuthName, sizeof(unit.m_AuthName), "公司债 - 当年");
    m_CDCAuthority.insert(std::make_pair(unit.m_AuthValue, unit));
    unit.m_AuthValue = 6;
    FIELDCOPYN(unit.m_AuthName, sizeof(unit.m_AuthName),
               "资产支持证券票据 - 当年");
    m_CDCAuthority.insert(std::make_pair(unit.m_AuthValue, unit));
    unit.m_AuthValue = 7;
    FIELDCOPYN(unit.m_AuthName, sizeof(unit.m_AuthName), "估值附属指标 - 当年");
    m_CDCAuthority.insert(std::make_pair(unit.m_AuthValue, unit));
    unit.m_AuthValue = 8;
    FIELDCOPYN(unit.m_AuthName, sizeof(unit.m_AuthName), "收益率曲线 - 当年");
    m_CDCAuthority.insert(std::make_pair(unit.m_AuthValue, unit));
    unit.m_AuthValue = 9;
    FIELDCOPYN(unit.m_AuthName, sizeof(unit.m_AuthName), "收益率曲线 - 历史");
    m_CDCAuthority.insert(std::make_pair(unit.m_AuthValue, unit));
    unit.m_AuthValue = 10;
    FIELDCOPYN(unit.m_AuthName, sizeof(unit.m_AuthName), "估值数据 - 历史");
    m_CDCAuthority.insert(std::make_pair(unit.m_AuthValue, unit));
  }

  uam::InitDecodeFuncs();

  qRegisterMetaType<xMarketSignalInfo_t>("xMarketSignalInfo_t");
}

SSUserAccountManager::~SSUserAccountManager(void) {}

#include <fstream>
namespace {
std::string __GetAppPath() {
  // TCHAR exeFullName[MAX_PATH]={0};
  //::GetModuleFileName(NULL,exeFullName,MAX_PATH);
  // CString Path=exeFullName;
  // int Pos= Path.ReverseFind( _T('\\'));
  // if(Pos==-1)
  //	return   _T(" "); //没有发现
  // Path=Path.Left(Pos);
  // if(Path.Right(1)==_T("\\ "))
  //	Path=Path.Left(Pos-1);
  // return Path;

  static std::string g_sPath = "";
  if (g_sPath.length() > 0) {
    return g_sPath;
  }

  char sPath[MAX_PATH] = {0};
  strcpy(sPath, FileSys::instance()->runRootDir().toStdString().c_str());
  char* p = strrchr(sPath, '\\');
  if (p) {
    *p = '\0';
  }
  g_sPath = sPath;
  return g_sPath;
}
}  // namespace

CLevelItemList& SSUserAccountManager::GetLevelList(const char* pType) {
  std::map<std::string, CLevelItemList>::iterator it = m_LevelList.find(pType);
  if (it == m_LevelList.end()) return LevelListNull;
  return it->second;
}

CLevelItemList& SSUserAccountManager::GetIRSLevelList() {
  return GetLevelList("IRS");
}

CLevelItemList& SSUserAccountManager::GetFXLevelList() {
  return GetLevelList("FX");
}

CLevelItemList& SSUserAccountManager::GetFXOptionLevelList() {
  return GetLevelList("FXOPTION");
}

CLevelItemList& SSUserAccountManager::GetBondLevelList() {
  return GetLevelList("Bond");
}

void SSUserAccountManager::InsertLevelItem(CLevelItem& item) {
  std::map<std::string, CLevelItemList>::iterator it =
      m_LevelList.find(item.m_BusinessType);
  if (it == m_LevelList.end()) {
    CLevelItemList levellist;
    levellist.Insert(item);
    m_LevelList.insert(std::pair<std::string, CLevelItemList>(
        std::string(item.m_BusinessType), levellist));
  } else {
    it->second.Insert(item);
  }
}

CBrokerList& SSUserAccountManager::GetBroker() {
  // DVIEW("SSUserAccountManager::GetBroker() READER
  // COUNT:%d",m_BrokerList.GetReaderCount());
  return m_BrokerList.GetWriter();
}
const CBrokerList& SSUserAccountManager::GetReadonlyBroker() {
  // DVIEW("SSUserAccountManager::GetReadonlyBroker() READER
  // COUNT:%d",m_BrokerList.GetReaderCount());
  return m_BrokerList.GetReader();
}
void SSUserAccountManager::UpdateBroker(const CBrokerList& brokerList) {
  m_BrokerList.Update(brokerList);
}
CQuoteBankList& SSUserAccountManager::GetQuoteBankList() {
  return m_BankQuoteList;
}

SSUserPermission& SSUserAccountManager::GetPermission() { return m_Permission; }

CSSUserWebOption& SSUserAccountManager::GetWebOption() { return m_WebOptions; }

CUserMemberInfo& SSUserAccountManager::GetUserMemberInfo() {
  return m_UserMemberInfo;
}

bool SSUserAccountManager::GetAllowBusinessAuth(CBusinessShowInfo& showinfo,
                                                const char* pBusinessCode) {
  showinfo.m_AllowList.clear();
  if (!pBusinessCode || strlen(pBusinessCode) <= 0) return false;
  CQuoteBankList& qbList = m_BankQuoteList;
  bool bShowPrimaryQuote = false;
  std::map<std::string, CQuoteBankUnit>::iterator ibank;
  for (ibank = qbList.m_mapBank.begin(); ibank != qbList.m_mapBank.end();
       ibank++) {
    std::list<xQBAuthorityBusiness_c>::iterator iAuth;
    for (iAuth = ibank->second.m_BusinessList.begin();
         iAuth != ibank->second.m_BusinessList.end(); iAuth++) {
      if (strcmp(iAuth->m_BusinessCode, pBusinessCode) ==
          0) {  // 一级行情非Broker 行情
        int nStatus = GetBussinessState(iAuth->m_Status_C, iAuth->m_Status_T,
                                        iAuth->m_Status_B);
        if (nStatus == typeApplyPass) {  // 审核通过才能看
          CShowUnitInfo unit;
          unit.m_BrokerID = iAuth->m_BrokerID;
          unit.m_AllowName = iAuth->m_AllowName;
          unit.m_AllowNameEn = iAuth->m_AllowNameEn;
          unit.m_Abbr = iAuth->m_Abbr;
          unit.m_BusinessCode = iAuth->m_BusinessCode;
          unit.m_BusinessLevel = iAuth->m_BusinessLevel;
          unit.m_Order = -1;
          showinfo.m_AllowList.push_back(unit);
          bShowPrimaryQuote = true;
        }
      }
    }
  }
  return bShowPrimaryQuote;
}

// void SSUserAccountManager::CheckIDCPermission(LPCSTR brokerID, bool& idc,
// bool& idcconnect)
// {
// 	idc = false; idcconnect = false;
// 	if (NULL == brokerID || strlen(brokerID) <= 0)return;
// 	std::map<std::string, UAM_IDCPermission>::iterator it =
// m_IDCPermission.find(std::string(brokerID)); 	if (it ==
// m_IDCPermission.end())return; 	idc = it->second.idc; 	idcconnect =
// it->second.idcconnet; 	return;
// }

bool SSUserAccountManager::GetPrimaryMarketAuth_SupMark(
    CBusinessShowInfo& showinfo) {
  showinfo.m_AllowList.clear();
  bool bShowPrimaryQuote = false;

  for (std::vector<CShowUnitInfo>::iterator it =
           m_PrimaryAuth.m_AllowList.begin();
       it != m_PrimaryAuth.m_AllowList.end(); it++) {
    if (it->m_BusinessCode == "BOND_P.SuperMarket") {
      showinfo.m_AllowList.push_back(*it);
      bShowPrimaryQuote = true;
    }
  }
  return bShowPrimaryQuote;
}

bool SSUserAccountManager::GetPrimaryMarketAuth_FlagShip(
    CBusinessShowInfo& showinfo) {
  showinfo.m_AllowList.clear();

  // 优先级 BOND_P.LEADSHIP.WEB > BOND_P > BOND_P.PFUND.WEB > BOND_P.LEADSHIP
  //		10						20
  //30					40
  static int Bond_P = 20;

  std::map<std::string, std::map<int, CShowUnitInfo*>> FilterMap;
  std::vector<CShowUnitInfo>::iterator iter = m_PrimaryAuth.m_AllowList.begin();
  std::vector<CShowUnitInfo>::iterator end = m_PrimaryAuth.m_AllowList.end();
  for (; iter != end; ++iter) {
    if (iter->m_BusinessCode == "BOND_P.PA") {
      if (iter->m_BrokerID == "ff808181359f49e601359f6dbb83031a")  // 平安
      {
        FilterMap[iter->m_BrokerID][Bond_P] = &(*iter);
      }
    } else if (iter->m_BusinessCode == "BOND_P") {
      if (iter->m_BrokerID == "402880f034219aed0134219e10b00727"      // 宏源
          || iter->m_BrokerID == "ff80818146a41f860146d7b0edca1df6"   // 联讯
          || iter->m_BrokerID == "402880f034219aed013421d996481b3f")  // 建行
      {
        FilterMap[iter->m_BrokerID][Bond_P] = &(*iter);
      }
    } else if (iter->m_BusinessCode == "BOND_P.LEADSHIP") {
      static int Bond_P_Leadship = 40;

      if (iter->m_BrokerID == "1"                                    // 国利
          || iter->m_BrokerID == "402880f034219aed013421d9a2421b9b"  // 民生
          ||
          iter->m_BrokerID == "402880f034219aed0134219d67ef01f5"  // 北京农商行
          || iter->m_BrokerID == "402880f034219aed0134219d4fbe0125"  // 宁波银行
          || iter->m_BrokerID == "402880f034219aed013421d993771b27"  // 招商证券
          || iter->m_BrokerID == "ff808181359f49e601359f6da6ad02e0"  // 国开行
          //|| iter->m_BrokerID == "3428a92f55550616015556db627d0083"
          ////"ff80818146a41f860147420ca50641f5"		//蓝石北京
          //|| iter->m_BrokerID == "402880f034219aed0134219dfd55069b"
          ////中信建投
          //|| iter->m_BrokerID == "ff80818141120c920141c9a8f27b03d0"
          ////中融景诚
      ) {
        FilterMap[iter->m_BrokerID][Bond_P_Leadship] = &(*iter);
      }
    } else if (iter->m_BusinessCode == "BOND_P.LEADSHIP.WEB") {
      static int Bond_P_Leadship_Web = 10;
      // 旗舰店web版
      FilterMap[iter->m_BrokerID][Bond_P_Leadship_Web] = &(*iter);
    } else if (iter->m_BusinessCode == "BOND_P.PFUND.WEB") {
      static int Bond_P_PFund_Web = 30;
      // 旗舰店web版
      FilterMap[iter->m_BrokerID][Bond_P_PFund_Web] = &(*iter);
    }
  }

  std::map<std::string, std::map<int, CShowUnitInfo*>>::iterator filterIter =
      FilterMap.begin();
  std::map<std::string, std::map<int, CShowUnitInfo*>>::iterator filterEnd =
      FilterMap.end();
  for (; filterIter != filterEnd; ++filterIter) {
    if (!filterIter->second.empty()) {
      showinfo.m_AllowList.push_back(*(filterIter->second.begin()->second));
    }
  }

  return !showinfo.m_AllowList.empty();
}

bool SSUserAccountManager::GetPrimaryMarketAuth_FlagShip_V2(
    CBusinessShowInfo& showinfo) {
  showinfo.m_AllowList.clear();

  // 优先级 BOND_P.LEADSHIP.WEB > BOND_P > BOND_P.PFUND.WEB > BOND_P.LEADSHIP
  //		10						20
  //30					40
  static int Bond_P = 20;

  struct tmpShowInfo {
   public:
    CShowUnitInfo* pInfo;
    int tmpOrder;
  };
  int tmpOrder = 0;
  std::map<std::string, std::map<int, tmpShowInfo>> FilterMap;
  std::vector<CShowUnitInfo>::iterator iter = m_PrimaryAuth.m_AllowList.begin();
  std::vector<CShowUnitInfo>::iterator end = m_PrimaryAuth.m_AllowList.end();
  for (; iter != end; ++iter) {
    if (iter->m_BusinessCode == "BOND_P.PA") {
      if (iter->m_BrokerID == "ff808181359f49e601359f6dbb83031a")  // 平安
      {
        FilterMap[iter->m_BrokerID][Bond_P].pInfo = &(*iter);
        FilterMap[iter->m_BrokerID][Bond_P].tmpOrder = tmpOrder++;
      }
    } else if (iter->m_BusinessCode == "BOND_P") {
      if (iter->m_BrokerID == "402880f034219aed0134219e10b00727"      // 宏源
          || iter->m_BrokerID == "ff80818146a41f860146d7b0edca1df6"   // 联讯
          || iter->m_BrokerID == "402880f034219aed013421d996481b3f")  // 建行
      {
        FilterMap[iter->m_BrokerID][Bond_P].pInfo = &(*iter);
        FilterMap[iter->m_BrokerID][Bond_P].tmpOrder = tmpOrder++;
      }
    } else if (iter->m_BusinessCode == "BOND_P.LEADSHIP") {
      static int Bond_P_Leadship = 40;

      if (iter->m_BrokerID == "1"                                    // 国利
          || iter->m_BrokerID == "402880f034219aed013421d9a2421b9b"  // 民生
          ||
          iter->m_BrokerID == "402880f034219aed0134219d67ef01f5"  // 北京农商行
          || iter->m_BrokerID == "402880f034219aed0134219d4fbe0125"  // 宁波银行
          || iter->m_BrokerID == "402880f034219aed013421d993771b27"  // 招商证券
          || iter->m_BrokerID == "ff808181359f49e601359f6da6ad02e0"  // 国开行
          //|| iter->m_BrokerID == "3428a92f55550616015556db627d0083"
          ////"ff80818146a41f860147420ca50641f5"		//蓝石北京
          //|| iter->m_BrokerID == "402880f034219aed0134219dfd55069b"
          ////中信建投
          //|| iter->m_BrokerID == "ff80818141120c920141c9a8f27b03d0"
          ////中融景诚
      ) {
        FilterMap[iter->m_BrokerID][Bond_P_Leadship].pInfo = &(*iter);
        FilterMap[iter->m_BrokerID][Bond_P_Leadship].tmpOrder = tmpOrder++;
      }
    } else if (iter->m_BusinessCode == "BOND_P.LEADSHIP.WEB") {
      static int Bond_P_Leadship_Web = 10;
      // 旗舰店web版
      FilterMap[iter->m_BrokerID][Bond_P_Leadship_Web].pInfo = &(*iter);
      FilterMap[iter->m_BrokerID][Bond_P_Leadship_Web].tmpOrder = tmpOrder++;
    }
  }

  std::map<std::string, std::map<int, tmpShowInfo>>::iterator filterIter =
      FilterMap.begin();
  std::map<std::string, std::map<int, tmpShowInfo>>::iterator filterEnd =
      FilterMap.end();
  for (; filterIter != filterEnd; ++filterIter) {
    if (!filterIter->second.empty()) {
      showinfo.m_AllowList.push_back(
          *(filterIter->second.begin()->second.pInfo));
      showinfo.m_AllowList.back().m_Order =
          filterIter->second.begin()->second.tmpOrder;
    }
  }
  sort(showinfo.m_AllowList.begin(), showinfo.m_AllowList.end(),
       [](const CShowUnitInfo& l, const CShowUnitInfo& r) -> bool {
         return l.m_Order < r.m_Order;
       });
  return !showinfo.m_AllowList.empty();
}

bool SSUserAccountManager::GetPrimaryMarketAuthForSuperMarket(
    CBusinessShowInfo& showinfo) {
  showinfo.m_AllowList.clear();

  // 优先级 BOND_P.LEADSHIP.WEB > BOND_P > BOND_P.LEADSHIP > BOND_P.SuperMarket
  //		10						20
  //30					40
  static int Bond_P = 20;

  std::map<std::string, std::map<int, CShowUnitInfo*>> FilterMap;
  std::vector<CShowUnitInfo>::iterator iter = m_PrimaryAuth.m_AllowList.begin();
  std::vector<CShowUnitInfo>::iterator end = m_PrimaryAuth.m_AllowList.end();
  for (; iter != end; ++iter) {
    if (iter->m_BusinessCode == "BOND_P.PA") {
      if (iter->m_BrokerID == "ff808181359f49e601359f6dbb83031a")  // 平安
      {
        FilterMap[iter->m_BrokerID][Bond_P] = &(*iter);
      }
    } else if (iter->m_BusinessCode == "BOND_P") {
      if (iter->m_BrokerID == "402880f034219aed0134219e10b00727"      // 宏源
          || iter->m_BrokerID == "ff80818146a41f860146d7b0edca1df6"   // 联讯
          || iter->m_BrokerID == "402880f034219aed013421d996481b3f")  // 建行
      {
        FilterMap[iter->m_BrokerID][Bond_P] = &(*iter);
      }
    } else if (iter->m_BusinessCode == "BOND_P.LEADSHIP") {
      static int Bond_P_Leadship = 30;

      if (iter->m_BrokerID == "1"                                    // 国利
          || iter->m_BrokerID == "402880f034219aed013421d9a2421b9b"  // 民生
          ||
          iter->m_BrokerID == "402880f034219aed0134219d67ef01f5"  // 北京农商行
          || iter->m_BrokerID == "402880f034219aed0134219d4fbe0125"  // 宁波银行
          || iter->m_BrokerID == "402880f034219aed013421d993771b27"  // 招商证券
          || iter->m_BrokerID == "ff808181359f49e601359f6da6ad02e0"  // 国开行
          // 纯web页面在超级新债通内不显示 (zhang)
          //|| iter->m_BrokerID == "3428a92f55550616015556db627d0083"
          ////"ff80818146a41f860147420ca50641f5"		//蓝石北京
          //|| iter->m_BrokerID == "402880f034219aed0134219dfd55069b"
          ////中信建投
          //|| iter->m_BrokerID == "ff80818141120c920141c9a8f27b03d0"
          ////中融景诚
      ) {
        FilterMap[iter->m_BrokerID][Bond_P_Leadship] = &(*iter);
      }
    } else if (iter->m_BusinessCode == "BOND_P.LEADSHIP.WEB") {
      static int Bond_P_Leadship_Web = 10;
      // 旗舰店web版
      FilterMap[iter->m_BrokerID][Bond_P_Leadship_Web] = &(*iter);
    } else if (iter->m_BusinessCode == "BOND_P.SuperMarket") {
      static int Bond_P_SuperMarket = 40;
      // 旗舰店web版
      FilterMap[iter->m_BrokerID][Bond_P_SuperMarket] = &(*iter);
    }
  }

  std::map<std::string, std::map<int, CShowUnitInfo*>>::iterator filterIter =
      FilterMap.begin();
  std::map<std::string, std::map<int, CShowUnitInfo*>>::iterator filterEnd =
      FilterMap.end();
  for (; filterIter != filterEnd; ++filterIter) {
    if (!filterIter->second.empty()) {
      showinfo.m_AllowList.push_back(*(filterIter->second.begin()->second));
    }
  }

  return !showinfo.m_AllowList.empty();
}

bool SSUserAccountManager::GetDimsumAuth_FlagShip(
    CBusinessShowInfo& showinfo) {  // DIMSUM.LEADSHIP
  showinfo.m_AllowList.clear();
  // bool bShowPrimaryQuote = false;

  for (std::vector<CShowUnitInfo>::iterator it =
           m_PrimaryAuth.m_AllowList.begin();
       it != m_PrimaryAuth.m_AllowList.end(); it++) {
    if (it->m_BusinessCode == "DIMSUM.LEADSHIP") {
      if (it->m_BrokerID != "ff80818140587874014061d76b985f56")
        continue;  // 中银香港
    } else {
      continue;
    }

    showinfo.m_AllowList.push_back(*it);
  }
  return !showinfo.m_AllowList.empty();
}

bool SSUserAccountManager::GetPrimaryMarketAuth_All(
    CBusinessShowInfo& showinfo) {  // BOND_P + BOND_P.PA + BOND_P.LEADSHIP +
                                    // BOND_P.SuperMarket
  showinfo.m_AllowList.clear();
  bool bShowPrimaryQuote = false;

  for (std::vector<CShowUnitInfo>::iterator it =
           m_PrimaryAuth.m_AllowList.begin();
       it != m_PrimaryAuth.m_AllowList.end(); it++) {
    if (it->m_BusinessCode.find("BOND_P") != std::string::npos) {
      showinfo.m_AllowList.push_back(*it);
      bShowPrimaryQuote = true;
    }
  }
  return bShowPrimaryQuote;
}

bool SSUserAccountManager::IsHavePrimaryAuth(const char* pszUwid) {
  if (pszUwid == NULL || strlen(pszUwid) == 0) return false;

  for (std::vector<CShowUnitInfo>::iterator it =
           m_PrimaryAuth.m_AllowList.begin();
       it != m_PrimaryAuth.m_AllowList.end(); it++) {
    CShowUnitInfo& ui = *it;

    if (ui.m_BrokerID.compare(pszUwid) == 0) return true;
  }

  return false;
}

bool SSUserAccountManager::IsHavePrimaryAuth(const char* pszUwid,
                                             const char* pszAuth) {
  if (pszUwid == NULL || strlen(pszUwid) == 0) return false;
  if (pszAuth == NULL || strlen(pszAuth) == 0) return false;

  bool bRet = false;
  for (std::vector<CShowUnitInfo>::iterator it =
           m_PrimaryAuth.m_AllowList.begin();
       it != m_PrimaryAuth.m_AllowList.end(); it++) {
    CShowUnitInfo& ui = *it;
    if (ui.m_BusinessCode.compare(pszAuth) == 0 &&
        ui.m_BrokerID.compare(pszUwid) == 0) {
      bRet = true;
      break;
    }
  }

  return bRet;
}

#define IgnoreSameAuth                                  \
  bool bexist = false;                                  \
  for (std::vector<CShowUnitInfo>::iterator it2 =       \
           m_PrimaryAuth.m_AllowList.begin();           \
       it2 != m_PrimaryAuth.m_AllowList.end(); it2++) { \
    if (it2->m_BrokerID == it->m_BrokerID) {            \
      bexist = true;                                    \
      break;                                            \
    }                                                   \
  }                                                     \
  if (!bexist) m_PrimaryAuth.m_AllowList.push_back(*it);

void SSUserAccountManager::UpdatePrimaryAuth() {
  m_PrimaryAuth.m_AllowList.clear();
  CBusinessShowInfo ibinfo;

  GetAllowBusinessAuth(ibinfo, "BOND_P.LEADSHIP.WEB");
  for (std::vector<CShowUnitInfo>::iterator it = ibinfo.m_AllowList.begin();
       it != ibinfo.m_AllowList.end(); it++) {
    m_PrimaryAuth.m_AllowList.push_back(*it);
  }

  GetAllowBusinessAuth(ibinfo, "BOND_P");
  for (std::vector<CShowUnitInfo>::iterator it = ibinfo.m_AllowList.begin();
       it != ibinfo.m_AllowList.end(); it++) {
    IgnoreSameAuth
  }

  GetAllowBusinessAuth(ibinfo, "BOND_P.PA");
  for (std::vector<CShowUnitInfo>::iterator it = ibinfo.m_AllowList.begin();
       it != ibinfo.m_AllowList.end(); it++) {
    m_PrimaryAuth.m_AllowList.push_back(*it);
  }

  GetAllowBusinessAuth(ibinfo, "BOND_P.PFUND.WEB");
  for (std::vector<CShowUnitInfo>::iterator it = ibinfo.m_AllowList.begin();
       it != ibinfo.m_AllowList.end(); it++) {
    IgnoreSameAuth
  }

  GetAllowBusinessAuth(ibinfo, "BOND_P.LEADSHIP");
  for (std::vector<CShowUnitInfo>::iterator it = ibinfo.m_AllowList.begin();
       it != ibinfo.m_AllowList.end(); it++) {
    IgnoreSameAuth
  }

  GetAllowBusinessAuth(ibinfo, "BOND_P.SuperMarket");
  for (std::vector<CShowUnitInfo>::iterator it = ibinfo.m_AllowList.begin();
       it != ibinfo.m_AllowList.end(); it++) {
    IgnoreSameAuth
  }

  GetAllowBusinessAuth(ibinfo, "DIMSUM.LEADSHIP");
  for (std::vector<CShowUnitInfo>::iterator it = ibinfo.m_AllowList.begin();
       it != ibinfo.m_AllowList.end(); it++) {
    IgnoreSameAuth
  }

  return;
}

void SSUserAccountManager::SetPrimaryAuthOrder(const char* pUUID, int Order) {
  if (!pUUID || strlen(pUUID) <= 0) return;
  for (std::vector<CShowUnitInfo>::iterator it =
           m_PrimaryAuth.m_AllowList.begin();
       it != m_PrimaryAuth.m_AllowList.end(); it++) {
    if (strcmp(it->m_BrokerID.c_str(), pUUID) == 0) {
      it->m_Order = Order;
      return;
    }
  }
  return;
}

bool _primary_order(
    const CShowUnitInfo& pfirst,
    const CShowUnitInfo& psecond)  // 如果该vector存入的是对象的话该函数参数须是
{
  if (pfirst.m_Order < 0) return false;
  if (psecond.m_Order < 0) return true;
  return pfirst.m_Order < psecond.m_Order;
};

void SSUserAccountManager::SortPrimayMarketAuth() {
  std::sort(m_PrimaryAuth.m_AllowList.begin(), m_PrimaryAuth.m_AllowList.end(),
            _primary_order);
  return;
}

bool SSUserAccountManager::GetFXSwapAuth(CBusinessShowInfo& showinfo) {
  return GetAllowBusinessAuth(showinfo, "FX");
}

bool SSUserAccountManager::GetFXOptionAuth(
    CBusinessShowInfo& showinfo) {  // FX Option权限
  return GetAllowBusinessAuth(showinfo, "FXOPTION");
}

bool SSUserAccountManager::GetFXAuth(
    CBusinessShowInfo& showinfo) {  // FX Swap + FX Option权限
  showinfo.m_AllowList.clear();
  bool bShow = false;
  CBusinessShowInfo ibinfo;
  bShow |= GetFXSwapAuth(ibinfo);
  for (std::vector<CShowUnitInfo>::iterator it = ibinfo.m_AllowList.begin();
       it != ibinfo.m_AllowList.end(); it++) {
    showinfo.m_AllowList.push_back(*it);
  }

  bShow |= GetFXOptionAuth(ibinfo);
  for (std::vector<CShowUnitInfo>::iterator it = ibinfo.m_AllowList.begin();
       it != ibinfo.m_AllowList.end(); it++) {
    showinfo.m_AllowList.push_back(*it);
  }

  return bShow;
}

bool SSUserAccountManager::GetNCDAuth(CBusinessShowInfo& showinfo) {
  showinfo.m_AllowList.clear();
  CQuoteBankList& qbList = m_BankQuoteList;
  bool bRet = false;
  std::map<std::string, CQuoteBankUnit>::iterator ibank;
  for (ibank = qbList.m_mapBank.begin(); ibank != qbList.m_mapBank.end();
       ibank++) {
    std::list<xQBAuthorityBusiness_c>::iterator iAuth;
    for (iAuth = ibank->second.m_BusinessList.begin();
         iAuth != ibank->second.m_BusinessList.end(); iAuth++) {
      if (strcmp(iAuth->m_BusinessCode, "NCD_P") == 0) {  // 一级分销NCD
        int nStatus = GetBussinessState(iAuth->m_Status_C, iAuth->m_Status_T,
                                        iAuth->m_Status_B);
        if (nStatus != typeApplyNPass && nStatus != typeStop &&
            nStatus !=
                typeNull) {  // 在黑名单的，或者申请不通过的，或者停用的，不可以看
          CShowUnitInfo unit;
          unit.m_BrokerID = iAuth->m_BrokerID;
          unit.m_AllowName = iAuth->m_AllowName;
          unit.m_AllowNameEn = iAuth->m_AllowNameEn;
          unit.m_BusinessLevel = iAuth->m_BusinessLevel;
          showinfo.m_AllowList.push_back(unit);
          bRet = true;
        }
      }
    }
  }
  return bRet;
}

bool SSUserAccountManager::GetBankQuoteAuth(CBusinessShowInfo& showinfo) {
  return GetAllowBusinessAuth(showinfo, "BOND");
}

bool SSUserAccountManager::GetOTCOBackgroundAuth(
    CBusinessShowInfo& showinfo)  // 可进入的场外期权后台列表(By Lance)
{
  return GetAllowBusinessAuth(showinfo, "OPTION_F.background");
}
bool SSUserAccountManager::GetOTCOForegroundAuth(
    CBusinessShowInfo& showinfo)  // 可进入的场外期权前台列表(By Lance)
{
  return GetAllowBusinessAuth(showinfo, "OPTION_F");
}

bool SSUserAccountManager::GetInvestRestrictionAuth(
    CBusinessShowInfo& showinfo)  // 获取投资限制权限列表(By Lance 2016.1.7)
{
  return GetAllowBusinessAuth(showinfo, "INVEST.RESTRICTION");
}

bool SSUserAccountManager::SetBrokerDailyCompany(const void* pData) {
  if (!pData) return false;

  xQBBrokerDailyCompanyAck_c* ptr = (xQBBrokerDailyCompanyAck_c*)pData;

  CBrokerList::Writer writer = GetBroker();
  writer.SetCompanyList(ptr->m_List);
  return true;
}

bool SSUserAccountManager::SetUserCSInfo(const void* pData) {
  if (!pData) return false;
  xQBAccountManagerAck_c* ptr = ((xQBAccountManagerAck_c*)(pData));

  xQBAccountManagerData unit;
  for (std::list<xQBAccountManagerData>::iterator it = ptr->m_data.begin();
       it != ptr->m_data.end(); ++it) {
    FIELDCOPY(m_UserInfo.m_CSQBAccount, it->m_CSQBAccount);
    FIELDCOPY(m_UserInfo.m_CSChineseName, it->m_CSChineseName);
    FIELDCOPY(m_UserInfo.m_CSEnglishName, it->m_CSEnglishName);
    FIELDCOPY(m_UserInfo.m_CSTelephone, it->m_CSTelephone);
    FIELDCOPY(m_UserInfo.m_CSMobile, it->m_CSMobile);
    FIELDCOPY(m_UserInfo.m_CSEmail, it->m_CSEmail);
    m_UserInfo.m_CSAgent = it->m_CSAgent;
    break;
  }

  return true;
}

bool SSUserAccountManager::GetBrokerNameByID(int ID, char* strCompanyName,
                                             size_t nSize,
                                             const char* strLanguage) {
  const CBrokerList& brokerlist = GetReadonlyBroker();
  CBrokerList::BrokerMap::const_iterator it =
      brokerlist.GetBrokerMap().find(ID);
  if (it != brokerlist.GetBrokerMap().end()) {
    if (strCompanyName) {
      if (strLanguage && strcmp(strLanguage, "EN") == 0) {
        FIELDCOPYN(strCompanyName, nSize, it->second.m_brokerENName.c_str());
      } else {  //"CHS"
        FIELDCOPYN(strCompanyName, nSize, it->second.m_brokerName.c_str());
      }
    }
    return true;
  } else
    return false;
}

const char* SSUserAccountManager::GetGlobleVariabl(
    int nKey) {  // 获取全局开关，全市场设置
  std::map<std::string, std::string>::iterator itor = m_SystemVariabls.end();
  switch (nKey) {
    case PageOnFlag:
      itor = m_SystemVariabls.find("PageOnFlag");
      break;
    case ShowBrokerFlag:
      itor = m_SystemVariabls.find("ShowBrokerFlag");
      break;
    case RatingInstutionSort:
      itor = m_SystemVariabls.find("rating_instution_sort");
      break;
    case WarningPayment:
      itor = m_SystemVariabls.find("warning_payment");
      break;
    case RecommendPageGetBpId:
      itor = m_SystemVariabls.find("recommend_page_get_bp_id");
      break;
    case MobileVerifyTime:
      itor = m_SystemVariabls.find("qb_mobile_verify_time");
      break;
    case ShowQidianBar:
      itor = m_SystemVariabls.find("qb_showqidianbar");
      break;
    case ShowTFStatisticsOverView:
      itor = m_SystemVariabls.find("qb_tfstatistics_overview");
      break;
    case ShowQBLiveOverAll:
      itor = m_SystemVariabls.find("qb_qblive_overall");
      break;
    case PageHomeUseNewIndex:
      itor = m_SystemVariabls.find("qb_pagehome_usenewindex");
      break;
    case ShowBestPriceSettlement:
      itor = m_SystemVariabls.find("qb_show_settlement");
      break;
    case HideSettlementSpot:
      itor = m_SystemVariabls.find("qb_hide_settlement_spot");
      break;
    case ExchangeSSESwitch:
      itor = m_SystemVariabls.find(SWITCH_QB_EXCHANGE_SSE);
      break;
    case ExchangeSZESwitch:
      itor = m_SystemVariabls.find(SWITCH_QB_EXCHANGE_SZE);
      break;
    case SwitchExchangeService:
      itor = m_SystemVariabls.find(SWITCH_QB_EXCHANGE_SERVICE);
      break;
    case UseNewDealSource:
      itor = m_SystemVariabls.find("qb_use_new_deal_source");
      break;
    case ShowNewDealDetail:
      itor = m_SystemVariabls.find("qb_show_new_deal_detail");
      break;
    default:
      break;
  }
  if (itor != m_SystemVariabls.end()) return itor->second.c_str();
  return "";
}

// bool SSUserAccountManager::GetCFETS_Right()
// //获取是否有权看外汇交易中心标志，旧
//{
//	return false;//20150609  lance要求去掉
// }

bool SSUserAccountManager::GetCFETS_Permission()  // 获取是否有权看外汇交易中心标志，3.4.0，Addby
                                                  // Lance 20170125
{
  return strcmp(GetPermission().GetValue(USER_PERMISSION_WEBBOND_CFETS), "1") ==
         0;
}

bool SSUserAccountManager::GetCffex_Right()  // 获取是否有权看中金所行情标志
{                                            //
  return true;
}

bool SSUserAccountManager::
    GetExchange_Right()  // 获取是否有权看上海深圳交易所行情标志
{
  return true;
}

bool SSUserAccountManager::GetSSE_Permission() {
  return strcmp(GetPermission().GetValue(USER_PERMISSION_BOND_SSE), "1") == 0;
}

bool SSUserAccountManager::GetSZE_Permission() {
  return strcmp(GetPermission().GetValue(USER_PERMISSION_BOND_SZE), "1") == 0;
}

bool SSUserAccountManager::IsExchangeTimeSwitch(const char* listedMarket) {
  int nKey = ExchangeSSESwitch;
  if (strcmp(listedMarket, "SZE") == 0) {
    nKey = ExchangeSZESwitch;
  }
  const char* sVal = GetGlobleVariabl(nKey);
  return (strcmp(sVal, "1") == 0);
}

// 获取Excel历史数据权限
bool SSUserAccountManager::GetExcelHistoryAuth() {
  const char* sValue = GetPermission().GetValue(USER_PERMISSION_EXCEL_HISTORY);
  return strcmp(sValue, "1") == 0 || strcmp(sValue, "2") == 0;
}

bool SSUserAccountManager::GetExcelRealAuth() {
  const char* sValue = GetPermission().GetValue(USER_PERMISSION_EXCEL_REAL);
  return strcmp(sValue, "1") == 0 || strcmp(sValue, "2") == 0;
}

bool SSUserAccountManager::GetExcelFunctionAuth() {
  const char* sValue = GetPermission().GetValue(USER_PERMISSION_EXCEL_FUNCTION);
  return strcmp(sValue, "1") == 0 || strcmp(sValue, "2") == 0;
}

bool SSUserAccountManager::GetExcelLoginAuth() {
  const char* sValue = GetPermission().GetValue(USER_PERMISSION_EXCEL_LOGIN);
  return strcmp(sValue, "1") == 0 || strcmp(sValue, "2") == 0;
}

CUserAccountInfo& SSUserAccountManager::GetUserInfo() { return m_UserInfo; }

CUserMobileConfirmInfo& SSUserAccountManager::GetMobileConfirm() {
  return m_MobileConfirm;
}

bool SSUserAccountManager::SetUserInfo(const void* pData, int nFuncID) {
  if (!pData) return false;

  switch (nFuncID) {
    case E_FID_QB_MODIFY_PASSWORD: {
      QBAccountInfoMdfReq_t* pAcc = (QBAccountInfoMdfReq_t*)pData;
      FIELDCOPY(m_UserInfo.m_Password, pAcc->m_Password);  // 用户密码
      break;
    }
    case E_FID_QB_QUERY_NEW_UERINFO_REQ: {
      QBAccountInfoNewAck_t* pAcc = (QBAccountInfoNewAck_t*)pData;
      if (pAcc->m_UserId[0] != 0)
        FIELDCOPY(m_UserInfo.m_UserId, pAcc->m_UserId);  // 用户id
      if (pAcc->m_Password[0] != 0)
        FIELDCOPY(m_UserInfo.m_Password, pAcc->m_Password);  // 用户密码
      if (pAcc->m_DisplayName[0] != 0)
        FIELDCOPY(m_UserInfo.m_DisplayName, pAcc->m_DisplayName);  // 用户显示名
      if (pAcc->m_DisplayName_Utf8[0] != 0)
        FIELDCOPY(m_UserInfo.m_DisplayName_Utf8,
                  pAcc->m_DisplayName_Utf8);  // 用户显示名，utf8编码
      if (pAcc->m_CompanyName[0] != 0)
        FIELDCOPY(m_UserInfo.m_CompanyName, pAcc->m_CompanyName);  // 所属机构
      if (pAcc->m_AccountType[0] != 0)
        FIELDCOPY(m_UserInfo.m_AccountType, pAcc->m_AccountType);  // 账号类型
      if (pAcc->m_UserName[0] != 0)
        FIELDCOPY(m_UserInfo.m_UserAccount, pAcc->m_UserName);  // 用户名 邮箱号

      if (pAcc->m_CompanyId[0] != 0)
        FIELDCOPY(m_UserInfo.m_CompanyId, pAcc->m_CompanyId);  // 所属机构ID
      if (pAcc->m_Telephone[0] != 0)
        FIELDCOPY(m_UserInfo.m_Telephone, pAcc->m_Telephone);  // 电话
      if (pAcc->m_Mobile[0] != 0)
        FIELDCOPY(m_UserInfo.m_Mobile, pAcc->m_Mobile);  // 手机
      if (pAcc->m_Rm[0] != 0)
        FIELDCOPY(m_UserInfo.m_Rm, pAcc->m_Rm);  // Reuters Messager
      if (pAcc->m_Msn[0] != 0) FIELDCOPY(m_UserInfo.m_Msn, pAcc->m_Msn);  // msn
      if (pAcc->m_QQ[0] != 0) FIELDCOPY(m_UserInfo.m_QQ, pAcc->m_QQ);
      if (pAcc->m_Address[0] != 0)
        FIELDCOPY(m_UserInfo.m_Address, pAcc->m_Address);  //
      if (pAcc->m_Department[0] != 0)
        FIELDCOPY(m_UserInfo.m_Department, pAcc->m_Department);  //
      if (pAcc->m_BussinessType[0] != 0)
        FIELDCOPY(m_UserInfo.m_BussinessType, pAcc->m_BussinessType);  //
      if (pAcc->m_Title[0] != 0)
        FIELDCOPY(m_UserInfo.m_Title, pAcc->m_Title);  // 用户名 邮箱号
      if (pAcc->m_QQEnterprise[0] != 0)
        FIELDCOPY(m_UserInfo.m_QQEnterprise,
                  pAcc->m_QQEnterprise);  // 企点QQ员工号
      if (pAcc->m_QQEnterprise_Company[0] != 0)
        FIELDCOPY(m_UserInfo.m_QQEnterprise_Company,
                  pAcc->m_QQEnterprise_Company);  // 企点QQ机构号

      char sExpire[64] = {0};
      FIELDCOPY(sExpire, pAcc->m_ExpireDate);  // 账号到期日
      if (sExpire[0] != '\0') {
        while (1) {
          int nL = strlen(sExpire);
          char* pos = strchr(sExpire, '-');
          if (pos && (pos - sExpire) < nL - 1) {
            memcpy(pos, pos + 1, nL - (pos - sExpire) - 1);
            sExpire[nL - 1] = '\0';
          } else
            break;
        }
      }
      if (sExpire[0] != 0) FIELDCOPY(m_UserInfo.m_ExpireDate, sExpire);

      for (std::list<xQBAccountInfoNewAckUnit>::const_iterator itrPhone =
               pAcc->m_lstPhone.begin();
           itrPhone != pAcc->m_lstPhone.end(); itrPhone++) {
        xQBAccountInfoNewAckUnit unit = *itrPhone;
        m_UserInfo.m_lstPhone.push_back(unit);
      }

      FileSys::instance()->setUserId(
          QString::fromLocal8Bit(m_UserInfo.m_UserAccount));

      normalNoArgEventDispatcher.dispatch(EVENT_USERINFO_READY);
      break;
    }
    case E_FID_QB_USEPROTOCAL_QUERY_REQ: {
      QBUseProtocolQueryAck* pAck = (QBUseProtocolQueryAck*)pData;
      if (strlen(pAck->m_UserId) <= 0) {
        m_bUseProtocol = false;
        break;
      }
      if (strcmp(pAck->m_UserId, m_UserInfo.m_UserId) != 0) {
        m_bUseProtocol = false;
        break;
      }
      // if (strcmp(pAck->m_UserAccount, m_UserInfo.m_UserAccount) != 0){
      // m_bUseProtocol = false; break; }
      if (strcmp(pAck->m_UserName, m_UserInfo.m_DisplayName) != 0) {
        m_bUseProtocol = false;
        break;
      }
      if (strcmp(pAck->m_InstitutionID, m_UserInfo.m_CompanyId) != 0) {
        m_bUseProtocol = false;
        break;
      }
      if (strcmp(pAck->m_InstitutionName, m_UserInfo.m_CompanyName) != 0) {
        m_bUseProtocol = false;
        break;
      }
      m_bUseProtocol = true;
      break;
    }
    case E_FID_QB_USER_SPONSORS: {
      QBUserSponsorsAct* pAck = (QBUserSponsorsAct*)pData;
      FIELDCOPY(m_UserInfo.m_SponsorsName, pAck->m_shortName);  // 赞助机构名称
      FIELDCOPY(m_UserInfo.m_SponsorsID, pAck->m_companyId);  // 赞助机构id
      break;
    }
    default:
      break;
  }
  return true;
}

bool SSUserAccountManager::SetUserInfo(const char* sUserID, const char* sPwdMD5,
                                       const char* sCompanyID) {
  if (!sUserID) return false;

  FIELDCOPY(m_UserInfo.m_UserId, sUserID);
  if (sPwdMD5) FIELDCOPY(m_UserInfo.m_Password, sPwdMD5);
  if (sCompanyID) FIELDCOPY(m_UserInfo.m_CompanyId, sCompanyID);
  return true;
}

bool SSUserAccountManager::SetBroker(const xQBTradeCmpyInfoListAck_c* plst) {
  if (!plst) return false;

  CBrokerList::Writer writer = GetBroker();
  for (auto it = plst->m_List.begin(); it != plst->m_List.end(); it++) {
    writer.UpdateBrokerInfo(*it);
  }

  m_bGotBrokerList = true;
  writer.GetBrokerList().SetSaveSortIdType(plst->m_SaveType);

  return true;
}

bool SSUserAccountManager::SetBrokerContacts(const std::string& sJson) {
  // 	std::string sTest = "{\
// \"meta\":{\
// \"errNum\":0,\
// \"errMsg\" : \"success\",\
// \"requestMethod\" : null,\
// \"requestURI\" : null\
// },\
// \"data\": [\
// {\
// \"brokerContactId\":14,\
// \"orgId\" : \"1\",\
// \"userId\" : \"9c26670bea354ca5bd5dbf59774432af\",\
// \"userNm\" : \"国利经纪人1\",\
// \"astParentTp\" : \"利率债\",\
// \"astChildTp\" : \"利率债\",\
// \"qm\" : \"@yace4980:qa.sumscope.cloud.com\",\
// \"qq\" : null,\
// \"rm\" : null\
// },\
// {\
// \"brokerContactId\":15,\
// \"orgId\" : \"1\",\
// \"userId\" : \"f92621e018024ad6b85a25b1100f60ea\",\
// \"userNm\" : \"国利经纪人2\",\
// \"astParentTp\" : \"信用债\",\
// \"astChildTp\" : \"信用债\",\
// \"qm\" : \"@yace4960:qa.sumscope.cloud.com\",\
// \"qq\" : null,\
// \"rm\" : null\
// },\
// {\
// \"brokerContactId\":16,\
// \"orgId\" : \"4\",\
// \"userId\" : \"212de425093649b58a678e3f59f8c181\",\
// \"userNm\" : \"平安经纪人1\",\
// \"astParentTp\" : \"NCD\",\
// \"astChildTp\" : \"NCD\",\
// \"qm\" : \"@yace4940:qa.sumscope.cloud.com\",\
// \"qq\" : null,\
// \"rm\" : null\
// },\
// {\
// \"brokerContactId\":17,\
// \"orgId\" : \"3\",\
// \"userId\" : \"7cc60b86970148b7bd8a18d6fa68fa7d\",\
// \"userNm\" : \"中诚经纪人1\",\
// \"astParentTp\" : \"信用债\",\
// \"astChildTp\" : \"高收益\",\
// \"qm\" : \"\",\
// \"qq\" : null,\
// \"rm\" : null\
// }\
// ]\
// }";
  //
  Json::Value js;
  Json::Reader rd;
  if (!rd.parse(sJson, js)) return false;

  m_BrokerContacts.clear();

  if (!js.isObject()) return false;
  Json::Value& jsData = js["data"];
  if (jsData.isNull() || !jsData.isArray()) return false;

  Json::ValueIterator it = jsData.begin();
  Json::ValueIterator ite = jsData.end();
  std::string sDept;
  for (int i = 0; it != ite; ++it, ++i) {
    Json::Value& jsUnit = jsData[i];
    Json::Value& jsBroker = jsUnit["orgId"];  // brokerid
    if (!jsBroker.isString()) continue;

    Json::Value& jsDept =
        jsUnit["astParentTp"];  // 经纪商台子，利率债，信用债，NCD
    if (!jsDept.isString()) continue;

    CBrokerContact bc;
    bc.m_brokerID = atoi(jsBroker.asString().c_str());
    sDept = jsDept.asString();
    if (sDept == "利率债") {
      bc.m_deptType = CBrokerContact::eDeptRating;
    } else if (sDept == "信用债") {
      bc.m_deptType = CBrokerContact::eDeptCredit;
    } else if (sDept == "NCD") {
      bc.m_deptType = CBrokerContact::eDeptNCD;
    }
    Json::Value& jsUserNm = jsUnit["userNm"];
    if (jsUserNm.isString()) bc.m_astNm = jsUserNm.asString();

    Json::Value& jsQM = jsUnit["qm"];  // 经纪人qmid
    if (jsQM.isString()) bc.m_qmid = jsQM.asString();

    auto itBroker = m_BrokerContacts.find(bc.m_brokerID);
    if (itBroker != m_BrokerContacts.end()) {
      auto& bcs = itBroker->second;
      bcs[bc.m_deptType] = bc;
    } else {
      CBrokerContacts bcs;
      bcs[bc.m_deptType] = bc;
      m_BrokerContacts[bc.m_brokerID] = bcs;
    }
  }
  return true;
}

bool SSUserAccountManager::HasBrokerList() { return m_bGotBrokerList; }

void SSUserAccountManager::SetAuthListFlag() { m_bGotAuthList = true; }

void SSUserAccountManager::InitIDCPermission() {
  m_IDCPermission.clear();

  CBusinessShowInfo si;
  GetAllowBusinessAuth(si, "IDC");
  for (std::vector<CShowUnitInfo>::iterator it = si.m_AllowList.begin();
       it != si.m_AllowList.end(); it++) {
    m_IDCPermission[it->m_BrokerID].idc = true;
  }

  si.m_AllowList.clear();
  GetAllowBusinessAuth(si, "IDC.CONNECT");
  for (std::vector<CShowUnitInfo>::iterator it = si.m_AllowList.begin();
       it != si.m_AllowList.end(); it++) {
    m_IDCPermission[it->m_BrokerID].idcconnet = true;
  }
}

void SSUserAccountManager::SetSystemVariabls(
    const std::map<std::string, std::string>& variableList) {
  m_SystemVariabls = variableList;
}

void SSUserAccountManager::SetCDCAutorityOld(int nAllow) {
  log_debug("Receive Old CDC Authority \'%d\'", nAllow);
  m_CDCAuthorityOld = nAllow;
}

int SSUserAccountManager::GetCDCAuthorityOld() { return m_CDCAuthorityOld; }

void SSUserAccountManager::SetCDCAutority(const void* pData) {
  m_CDCAuthoriryInit = true;
  if (!pData) {
    m_CDCAuthority.clear();
    return;
  }
  xCDCAuthorityAct_c* pAck = (xCDCAuthorityAct_c*)pData;
  if (strcmp(GetUserInfo().m_UserId, pAck->m_user.m_UserId) != 0 ||
      strcmp(GetUserInfo().m_CompanyId, pAck->m_user.m_CompanyId) != 0)
    return;

  char sDebug[128];
  char sTemp[8];
  memset(sDebug, 0, sizeof(sDebug));
  FIELDCOPY(sDebug, "Receive New CDC Authority [");
  for (auto it = pAck->m_AuthList.begin(); it != pAck->m_AuthList.end(); it++) {
    memset(sTemp, 0, sizeof(sTemp));
    FMTBUF(sTemp, "%d,", it->m_AuthValue);
    strcat(sDebug, sTemp);
    m_CDCAuthority.insert(std::make_pair(it->m_AuthValue, *it));
  }
  strcat(sDebug, "]");
  log_debug(sDebug);
}

void SSUserAccountManager::SetCSIAuthorityFlag(int flag) {
  m_CSIAuthorityFlag = (flag == 1);
}

bool SSUserAccountManager::GetCSIAuthorityFlag() const {
  return m_CSIAuthorityFlag;
}

const std::map<int, xCDCAuthorityUnit>& SSUserAccountManager::GetCDCAutority() {
  return m_CDCAuthority;
}
SSUserAccountManager::CDCAuthKey SSUserAccountManager::GetCDCAutorityKey() {
  if (m_CDCAuthority.empty()) return CDCAuthKey();
  CDCAuthKey authKey(m_CDCAuthority.rbegin()->first);
  for (CDCAuthorityUnitMap::iterator it = m_CDCAuthority.begin();
       it != m_CDCAuthority.end(); ++it) {
    authKey.SetKey(it->first);
  }
  return authKey;
}
bool SSUserAccountManager::HasAnyCDCAuthority() {
  if (!m_CDCAuthoriryInit) {
    return m_hasAnyCDCAuth;
  }
  m_hasAnyCDCAuth = false;
  auto& auth = GetCDCAutority();
  if (auth.size() > 0) {
    for (int i = 1; i <= 6; i++) {
      if (auth.find(i) != auth.end()) {
        m_hasAnyCDCAuth = true;
        break;
      }
    }
  }
  m_CDCAuthoriryInit = false;
  return m_hasAnyCDCAuth;
}

bool SSUserAccountManager::HasAuthOfCDC(int nAuthNo /* =7 */) {
  CDCAuthorityUnitMap::iterator itrFind = m_CDCAuthority.find(nAuthNo);

  return itrFind != m_CDCAuthority.end();
}

bool SSUserAccountManager::HasAuthOfCSI() {
  return strcmp(SSUserAccountManager::instance().GetPermission().GetValue(
                    USER_PERMISSION_CSI_IMPLICITRATING),
                "1") == 0;
}

bool SSUserAccountManager::HasAuthOfCBR() {
  return strcmp(SSUserAccountManager::instance().GetPermission().GetValue(
                    USER_PERMISSION_CHINABONDRATINGG),
                "1") == 0;
}

bool SSUserAccountManager::
    HasAuthOfSSE() {  // 可能偶发权限获取为false问题，在收到应答后重置权限初始化状态
  if (!m_initAuthSSE) {
    m_hasAuthSSE = GetSSE_Permission();
    m_initAuthSSE = true;
  }
  return m_hasAuthSSE;
}

bool SSUserAccountManager::HasAuthOfSZE() {
  if (!m_initAuthSZE) {
    m_hasAuthSZE = GetSZE_Permission();
    m_initAuthSZE = true;
  }
  return m_hasAuthSZE;
}

bool SSUserAccountManager::HasExchangeAuth(const char* lmMarket) {
  if (!lmMarket) return true;
  if (strcmp(lmMarket, "SSE") == 0) {
    return HasAuthOfSSE();
  } else if (strcmp(lmMarket, "SZE") == 0) {
    return HasAuthOfSZE();
  }
  return true;
}

void SSUserAccountManager::ResetExchangeInit() {
  m_initAuthSSE = false;
  m_hasAuthSZE = false;
}

bool SSUserAccountManager::IsSwitchExchangeService() {
  int nKey = SwitchExchangeService;
  const char* sVal = GetGlobleVariabl(nKey);
  return (strcmp(sVal, "1") == 0);
}

bool SSUserAccountManager::HasAuthList() { return m_bGotAuthList; }

void SSUserAccountManager::ResetBrokerList() { m_bGotBrokerList = false; }

bool SSUserAccountManager::AllowQuote() { return m_bQuoteAuth; }

void SSUserAccountManager::SetAllowQuoteFlag(int bAllowQuote) {
  if (bAllowQuote == 1)
    m_bQuoteAuth = true;
  else
    m_bQuoteAuth = false;
}

bool SSUserAccountManager::IsBrokerBondAvailable(const int& nCompanyID) {
  const CBrokerList& brokerlist = GetReadonlyBroker();
  CBrokerList::BrokerMap::const_iterator it =
      brokerlist.GetBrokerMap().find(nCompanyID);
  if (it == brokerlist.GetBrokerMap().end()) return false;
  return it->second.m_enableFlag_BOND;
}

bool SSUserAccountManager::IsBrokerBondAvailable(const char* sCompanyID) {
  if (sCompanyID) {
    int nCompanyID = atoi(sCompanyID);
    return IsBrokerBondAvailable(nCompanyID);
  } else
    return false;
}

bool SSUserAccountManager::IsBrokerNCDAvailable(const int& nCompanyID) {
  const CBrokerList& brokerlist = GetReadonlyBroker();
  CBrokerList::BrokerMap::const_iterator it =
      brokerlist.GetBrokerMap().find(nCompanyID);
  if (it == brokerlist.GetBrokerMap().end()) return false;
  return it->second.m_enableFlag_NCD;
}

bool SSUserAccountManager::IsBrokerNCDAvailable(const char* sCompanyID) {
  if (sCompanyID) {
    int nCompanyID = atoi(sCompanyID);
    return IsBrokerNCDAvailable(nCompanyID);
  } else
    return false;
}

bool SSUserAccountManager::IsBrokerIRSAvailable(const int& nCompanyID) {
  const CBrokerList& brokerlist = GetReadonlyBroker();
  CBrokerList::BrokerMap::const_iterator it =
      brokerlist.GetBrokerMap().find(nCompanyID);
  if (it == brokerlist.GetBrokerMap().end()) return false;
  return it->second.m_enableFlag_IRS;
}

bool SSUserAccountManager::SetQuoteBank(const void* pData) {
  if (!pData) return false;
  xQBBondBCInfoAck_c* plst = ((xQBBondBCInfoAck_c*)(pData));
  std::list<xQBBondBCUnit_c>::iterator it;
  for (it = plst->m_BCList.begin(); it != plst->m_BCList.end(); it++) {
    std::map<std::string, CQuoteBankUnit>::iterator itr =
        m_BankQuoteList.m_mapBank.find(it->m_BCCompanyID);
    if (itr != m_BankQuoteList.m_mapBank.end()) {
      itr->second.m_BCCode = it->m_BCCode;
      itr->second.m_BCCompanyID = it->m_BCCompanyID;
      itr->second.m_BCName = it->m_BCName;
      itr->second.m_BCDetail = it->m_BCDetail;
      itr->second.m_Contact = it->m_Contact;
    } else {
      CQuoteBankUnit ut;
      ut.m_BCCode = it->m_BCCode;
      ut.m_BCCompanyID = it->m_BCCompanyID;
      ut.m_BCName = it->m_BCName;
      ut.m_BCDetail = it->m_BCDetail;
      ut.m_Contact = it->m_Contact;

      m_BankQuoteList.m_mapBank[ut.m_BCCompanyID] = ut;
    }
  }
  return true;
}

void SSUserAccountManager::SetAccountUpdateInfo(
    const CUserAccountUpdateInfo& AccountUpdateInfo) {
  m_AccountUpdateData = AccountUpdateInfo;
}

CUserAccountUpdateInfo& SSUserAccountManager::GetAccountUpdateInfo(void) {
  return m_AccountUpdateData;
}

bool SSUserAccountManager::IsBrokerDealHistoryAvailable(int nBrokerID) {
  std::string strKey = USER_PERMISSION_BOND_DEALHIS;
  strKey.append(".");

  const CBrokerList& brokerlist = GetReadonlyBroker();
  CBrokerList::BrokerMap::const_iterator it =
      brokerlist.GetBrokerMap().find(nBrokerID);
  if (it == brokerlist.GetBrokerMap().end()) return false;

  strKey.append(it->second.m_brokerCode);
  transform(strKey.begin(), strKey.end(), strKey.begin(), tolower);
  if (std::string(m_Permission.GetValue(strKey.c_str())) == "1") return true;

  return false;
}

void SSUserAccountManager::SetQuoteSharedAccount(
    const CSSQuoteSharedAccount& QuoteSharedAcc) {
  m_QuoteSharedAccount = QuoteSharedAcc;
}

CSSQuoteSharedAccount& SSUserAccountManager::GetQuoteSharedAccount(void) {
  return m_QuoteSharedAccount;
}

bool SSUserAccountManager::GetPrimaryBrokerShowInfo(const char* sBrokerID,
                                                    CShowUnitInfo& info) {
  if (!sBrokerID || strlen(sBrokerID) <= 0) return false;

  for (std::vector<CShowUnitInfo>::iterator it =
           m_PrimaryAuth.m_AllowList.begin();
       it != m_PrimaryAuth.m_AllowList.end(); it++) {
    if (it->m_BrokerID == sBrokerID) {
      info = *it;
      return true;
    }
  }
  return false;
}

bool SSUserAccountManager::GetExcelBond_Broker(
    CBusinessShowInfo& showinfo)  // BOND_EXCEL,Excel插件broker权限
{
  return GetAllowBusinessAuth(showinfo, "BOND_EXCEL");
}

bool SSUserAccountManager::GetBondCopAuth(
    CBusinessShowInfo& showinfo)  // 机构债券报价权限
{
  return GetAllowBusinessAuth(showinfo, "BOND.COP");
}

void SSUserAccountManager::SetComsAccessID(const char* sAccessID) {
  if (sAccessID == NULL) {
    return;
  }

  memset(m_sComsAccessID, 0, sizeof(m_sComsAccessID));
  FIELDCOPY(m_sComsAccessID, sAccessID);
}

void SSUserAccountManager::requestSystime() {
  MessagePoster poster;
  poster.send(nullptr, 0, E_FID_SYS_TIME);
}

void SSUserAccountManager::requestBroker() {
  SSUserAccountManager::instance().ResetBrokerList();

  qb::SSRequestMsg Req;
  memset(&Req, 0, sizeof(qb::SSRequestMsg));
  Req.m_MsgType = qb::SSReqType_Message;
  Req.m_FuncID = E_FID_QB_ALL_CMPY_QRY;
  Req.m_pRequest = nullptr;

  log_debug("RequestBroker m_UserID = %s",
            qb::loginData::instance().UserInfo().strUserID.c_str());

  MessagePoster poster(&Req, [](qb::proto::Message& msg,
                                qb::SSRequestMsg* req) {
    qb::proto::VariantMap submsg;
    submsg.setString("UserId", qb::loginData::instance().UserInfo().strUserID);
    msg.SetMap("xQBTradeCmpyQryReq", submsg);
  });
  poster.send();
}

void SSUserAccountManager::requestQbFlags() {
  qb::SSRequestMsg req;
  req.m_FuncID = E_FID_QB_FLAGS_REQ;
  req.m_pRequest = nullptr;

  MessagePoster poster(
      &req, [](qb::proto::Message& msg, qb::SSRequestMsg* req) {
        qb::proto::VariantMap submsg;
        submsg.SetString(
            "CompanyID",
            SSUserAccountManager::instance().GetUserInfo().m_CompanyId);
        submsg.SetString(
            "UserID", SSUserAccountManager::instance().GetUserInfo().m_UserId);

        qb::proto::VariantMap submsg_flag;
        submsg_flag.SetString("Key", "");
        submsg_flag.SetString("Value", "");
        submsg.SetMap("Flag", submsg_flag);
        msg.SetMap("xQbFlagsReq", submsg);
      });
  poster.send();
}

void SSUserAccountManager::requestGlobalSwitch() {
  qb::SSRequestMsg Req;
  Req.m_FuncID = E_FID_QB_GLOBAL_SWITCH;
  Req.m_pRequest = nullptr;

  MessagePoster poster(
      &Req, [](qb::proto::Message& msg, qb::SSRequestMsg* req) {
        qb::proto::VariantMap submsg;
        submsg.setString("Version", "2.2.20150901");  // Hardcode?!
        submsg.setString(
            "UserID", SSUserAccountManager::instance().GetUserInfo().m_UserId);
        msg.SetMap("xQBGlobalSwitchReq", submsg);
      });

  poster.send();
}

void SSUserAccountManager::requestUserInfo() {
  qb::SSRequestMsg Req;
  Req.m_FuncID = E_FID_QB_QUERY_NEW_UERINFO_REQ;
  Req.m_pRequest = nullptr;

  MessagePoster poster(
      &Req, [](qb::proto::Message& msg, qb::SSRequestMsg* req) {
        qb::proto::VariantMap submsg;
        submsg.setString(
            "UserId", SSUserAccountManager::instance().GetUserInfo().m_UserId);
        msg.SetMap("xQBAccountInfoNewReq", submsg);
      });
  poster.send();
}

void SSUserAccountManager::requestUserProtocol() {
  qb::SSRequestMsg Req;
  Req.m_FuncID = E_FID_QB_USEPROTOCAL_QUERY_REQ;
  Req.m_pRequest = nullptr;

  MessagePoster poster(
      &Req, [](qb::proto::Message& msg, qb::SSRequestMsg* req) {
        qb::proto::VariantMap submsg;
        submsg.setString(
            "UserId", SSUserAccountManager::instance().GetUserInfo().m_UserId);
        msg.SetMap("xQBUseProtocolQueryReq", submsg);
      });
  poster.send();
}

void SSUserAccountManager::requestUserAuthority() {
  qb::SSRequestMsg Req;
  Req.m_FuncID = E_FID_QB_AUTHORITY_QUERY_NEW_REQ;

  MessagePoster poster(
      &Req, [](qb::proto::Message& msg, qb::SSRequestMsg* req) {
        qb::proto::VariantMap submsg;
        submsg.SetString(
            "UserId", SSUserAccountManager::instance().GetUserInfo().m_UserId);
        submsg.SetString(
            "CompanyId",
            SSUserAccountManager::instance().GetUserInfo().m_CompanyId);
        msg.SetMap("xQBAuthorityQueryReq", submsg);
      });
  poster.send();
}

void SSUserAccountManager::requestMobileConfirm() {
  qb::SSRequestMsg Req;
  Req.m_FuncID = E_FID_QB_MOBILE_VERIFY_INFO;
  Req.m_pRequest = nullptr;
  MessagePoster poster(
      &Req, [](qb::proto::Message& msg, qb::SSRequestMsg* req) {
        qb::proto::VariantMap submsg;
        submsg.SetString(
            "UserId", SSUserAccountManager::instance().GetUserInfo().m_UserId);
        msg.SetMap("xQBMobileVerifyInfoReq", submsg);
      });
  poster.send();
}

void SSUserAccountManager::requestUserMemInfo() {
  qb::SSRequestMsg Req;
  Req.m_FuncID = E_FID_QB_USER_MEMBER_INFO_REQ;

  MessagePoster poster(
      &Req, [](qb::proto::Message& msg, qb::SSRequestMsg* req) {
        qb::proto::VariantMap submsg;
        submsg.SetString(
            "UserId", SSUserAccountManager::instance().GetUserInfo().m_UserId);
        submsg.SetString(
            "UserAccount",
            SSUserAccountManager::instance().GetUserInfo().m_UserAccount);
        submsg.SetString(
            "CompanyId",
            SSUserAccountManager::instance().GetUserInfo().m_CompanyId);
        msg.SetMap("xUserMemberInfoReq", submsg);
      });
  poster.send();
}

void SSUserAccountManager::requestQBConditionGroupQueryNew() {
  qb::SSRequestMsg Req;
  Req.m_FuncID = E_FID_QB_CONDITION_GRUOP_REQ_NEW;

  MessagePoster poster(
      &Req, [](qb::proto::Message& msg, qb::SSRequestMsg* req) {
        qb::proto::VariantMap submsg;
        submsg.SetString(
            "UserId", SSUserAccountManager::instance().GetUserInfo().m_UserId);
        msg.SetMap("xQBConditionGroupReqNew", submsg);
      });
  poster.send();
}

void SSUserAccountManager::SetBrokerMobileOnline(bool bOnline) {
  m_bBrokerMobileOnline = bOnline;
}
bool SSUserAccountManager::IsBrokerMobileOnline() {
  return m_bBrokerMobileOnline;
}

bool SSUserAccountManager::IsShowSettlement() {
  const char* sVal = GetGlobleVariabl(ShowBestPriceSettlement);
  return (strcmp(sVal, "1") == 0 || strcmp(sVal, "") == 0);
}

bool SSUserAccountManager::IsHideSettlementSpot() {
  const char* sVal = GetGlobleVariabl(HideSettlementSpot);
  return (strcmp(sVal, "1") == 0);
}

bool SSUserAccountManager::isUsedProtocol() { return m_bUseProtocol; }

void SSUserAccountManager::SetBrokerDefaultContact(const xQBFlagsAck_c* ack) {
  if (ack->listFlags.size() <= 0) return;

  const char* szCont = nullptr;
  auto itC = ack->listFlags.begin();
  for (; itC != ack->listFlags.end(); itC++) {
    if (strcmp(itC->szKey, "BrokerDefaultContact") == 0) {
      szCont = itC->szValue;
      break;
    }
  }
  if (nullptr == szCont) return;

  Json::Value ja;
  Json::Reader rd;
  if (!rd.parse(szCont, ja)) return;
  if (!ja.isArray()) return;

  CBrokerList::Writer writer = GetBroker();
  auto it = ja.begin();
  auto ite = ja.end();
  std::string sType;
  int brokerID = 0;
  int cID = 0;
  for (int i = 0; it != ite; ++it, ++i) {
    const Json::Value& vBroker = ja[i]["brokerid"];
    brokerID = vBroker.isInt() ? vBroker.asInt() : -1;
    const Json::Value& vid = ja[i]["ctid"];
    cID = vid.isInt() ? vid.asInt() : -1;
    const Json::Value& vType = ja[i]["type"];
    sType = vType.isString() ? vType.asString() : "";

    if (brokerID >= 1 && cID >= 0 && sType.length() > 0) {
      writer.SetDefaultContact(brokerID, sType.c_str(), cID);
    }
  }
}

bool SSUserAccountManager::GetBrokerContact(int nBrokerID,
                                            CBrokerContact::eDeptType nType,
                                            CBrokerContact& brokerContact) {
  auto itBroker = m_BrokerContacts.find(nBrokerID);
  if (itBroker == m_BrokerContacts.end()) return false;

  auto& bcs = itBroker->second;
  auto itBC = bcs.find((int)nType);
  if (itBC == bcs.end()) return false;

  brokerContact = itBC->second;
  return true;
}
////////////////////////////////////////////////////////////////////////////////
const CBrokerUnit& CBrokerList::GetBrokerUnit(int brokerId) const {
  static CBrokerUnit unitEmpty;
  BrokerMap::const_iterator it = m_mapBroker.find(brokerId);
  if (it == m_mapBroker.end()) return unitEmpty;
  return it->second;
}

void CBrokerList::AddSortKey(const int& key) {
  auto findval = find(m_sortid.begin(), m_sortid.end(), key);
  if (findval == m_sortid.end()) m_sortid.push_back(key);
}

void CBrokerList::RemoveSortKey(const int& key) {
  for (size_t i = 0; i != m_sortid.size(); ++i) {
    if (m_sortid[i] == key) {
      m_sortid.erase(m_sortid.begin() + i);
      break;
    }
  }
}

void CBrokerList::IniSortKey() {
  for (BrokerMap::iterator it = m_mapBroker.begin(); it != m_mapBroker.end();
       it++) {
    int nID = it->first;
    AddSortKey(nID);
  }
}
////////////////////////////////////////////////////////////////////////////////
CBrokerList::Writer::~Writer() {
  if (m_changed_count++) {
    SSUserAccountManager::instance().UpdateBroker(m_brokerlist);
  }
}
void CBrokerList::Writer::ClearAllBusinessList() {
  m_changed_count++;
  for (auto bit = m_brokerlist.GetBrokerMap().begin();
       bit != m_brokerlist.GetBrokerMap().end(); ++bit) {
    bit->second.m_BusinessList.clear();
  }
}

void CBrokerList::Writer::AddBusiness(int brokerid,
                                      const xQBAuthorityBusiness_c& business) {
  m_changed_count++;
  m_brokerlist.GetBrokerMap()[brokerid].m_BusinessList.push_back(business);
}

void CBrokerList::Writer::ClearAllContactList() {
  m_changed_count++;
  for (auto bit = m_brokerlist.GetBrokerMap().begin();
       bit != m_brokerlist.GetBrokerMap().end(); ++bit) {
    bit->second.m_ContactList.clear();
  }
}

void CBrokerList::Writer::AddContact(int brokerid,
                                     const xQBTradeCmpContact_c& contact) {
  m_changed_count++;
  m_brokerlist.GetBrokerMap()[brokerid].m_ContactList.push_back(contact);
}

CBrokerList::BusinessList& CBrokerList::Writer::GetBusinessList(int brokerid) {
  m_changed_count++;
  return m_brokerlist.GetBrokerMap()[brokerid].m_BusinessList;
}

void CBrokerList::Writer::SetBONDEnableFlag(int brokerid, bool enable) {
  log_info("[STREAM][NCD] SetBONDEnableFlag(%d,%s)", brokerid,
           enable ? "true" : "false");
  m_changed_count++;
  m_brokerlist.GetBrokerMap()[brokerid].m_enableFlag_BOND = enable;
}

void CBrokerList::Writer::SetNCDEnableFlag(int brokerid, bool enable) {
  log_info("[STREAM][NCD] SetNCDEnableFlag(%d,%s)", brokerid,
           enable ? "true" : "false");
  m_changed_count++;
  m_brokerlist.GetBrokerMap()[brokerid].m_enableFlag_NCD = enable;
}

void CBrokerList::Writer::SetIRSEnableFlag(int brokerid, bool enable) {
  m_changed_count++;
  m_brokerlist.GetBrokerMap()[brokerid].m_enableFlag_IRS = enable;
}

void CBrokerList::Writer::SetQuotationSilent(int brokerid, bool bSilent) {
  m_changed_count++;
  m_brokerlist.GetBrokerMap()[brokerid].m_bQuotationSilent = bSilent;
}

void CBrokerList::Writer::Apply(int brokerid,
                                const std::string& sBusinessAllowId) {
  m_changed_count++;
  BusinessList& bl = GetBusinessList(brokerid);
  for (auto it = bl.begin(); it != bl.end(); it++) {
    if (strcmp(it->m_BusinessAllowId, sBusinessAllowId.c_str()) == 0) {
      it->m_bApplyed = true;
      break;
    }
  }
}

void CBrokerList::Writer::UpdateBrokerInfo(const xQBTradeCmpyInfo_c& cmpy) {
  m_changed_count++;
  CBrokerList::BrokerMap::iterator itBU =
      m_brokerlist.GetBrokerMap().find(cmpy.m_Id);
  ;
  if (itBU != m_brokerlist.GetBrokerMap().end()) {
    // 显式设置BrokerID防止其他线程在SetBroker之前先使用Broker信息
    itBU->second.m_brokerID = cmpy.m_Id;
    itBU->second.m_brokerCode = cmpy.m_Code;
    itBU->second.m_brokerName = cmpy.m_Name;
    itBU->second.m_brokerENName = cmpy.m_EnName;
    itBU->second.m_address = cmpy.m_Address;
    itBU->second.m_postCode = cmpy.m_PostCode;
    itBU->second.m_tel = cmpy.m_Tel;
    itBU->second.m_fax = cmpy.m_Fax;
    itBU->second.m_email = cmpy.m_Email;
    // itBU->second.m_enableFlag = false;
  } else {
    CBrokerUnit st;
    st.m_brokerID = cmpy.m_Id;
    st.m_brokerCode = cmpy.m_Code;
    st.m_brokerName = cmpy.m_Name;
    st.m_brokerENName = cmpy.m_EnName;
    st.m_address = cmpy.m_Address;
    st.m_postCode = cmpy.m_PostCode;
    st.m_tel = cmpy.m_Tel;
    st.m_fax = cmpy.m_Fax;
    st.m_email = cmpy.m_Email;
    // st.m_enableFlag = true;
    m_brokerlist.GetBrokerMap()[cmpy.m_Id] = st;
  }
  m_brokerlist.AddSortKey(cmpy.m_Id);
}

void CBrokerList::Writer::SetDefaultContact(int brokerid, const char* sKey,
                                            int contactid) {
  if (!sKey || sKey[0] == '\0' || contactid < 0) return;

  m_changed_count++;
  CBrokerList::BrokerMap::iterator itBU =
      m_brokerlist.GetBrokerMap().find(brokerid);
  if (itBU != m_brokerlist.GetBrokerMap().end()) {
    itBU->second.m_DefaultContact[sKey] = contactid;
  } else {
    CBrokerUnit st;
    st.m_brokerID = brokerid;
    st.m_DefaultContact[sKey] = contactid;
    m_brokerlist.GetBrokerMap()[brokerid] = st;
  }
  m_brokerlist.AddSortKey(brokerid);
}

////////////////////////////////////////////////////////////////////////////////
CBrokerListHost::CBrokerListHost() {
  m_reader.clear();
  m_writer.stateid = 0;
  m_writer.brokerlist = new CBrokerList();
}

CBrokerListHost::~CBrokerListHost() {
  CFastLock::Scoped scoped(m_lock);
  if (m_writer.brokerlist) {
    delete m_writer.brokerlist;
    m_writer.brokerlist = nullptr;
  }
  for (auto it = m_reader.begin(); it != m_reader.end(); ++it) {
    BrokerListInfo& bi = it->second;
    if (bi.brokerlist) {
      delete bi.brokerlist;
      bi.brokerlist = nullptr;
    }
  }
  m_reader.clear();
}

void CBrokerListHost::Update(const CBrokerList& broker) {
  // broker 已经被改动,需要更新到m_writer中
  // 调用方:
  // CBrokerList::Writer::~Writer() --> SSUserAccountManager::UpdateBroker()
  // SSM_METRICS(" update CBrokerList tid:%d
  // stateid:%d",GetCurrentThreadId(),m_writer.stateid+1);
  CFastLock::Scoped scoped(m_lock);
  m_writer.stateid++;
  *m_writer.brokerlist = broker;
}

CBrokerList& CBrokerListHost::GetReaderImpl() {
  // 安全的获取当前线程所拥有的一份拷贝
#ifdef WIN32
  DWORD tid = GetCurrentThreadId();
#else
  DWORD tid = (DWORD)pthread_self();
#endif
  CFastLock::Scoped scoped(m_lock);
  BrokerListInfoMap::iterator it = m_reader.find(tid);
  if (it == m_reader.end()) {
    SSM_METRICS("NEW THREAD:%d NEW CBrokerList", tid);
    BrokerListInfo bi;
    bi.stateid = m_writer.stateid;
    bi.brokerlist = new CBrokerList();
    *bi.brokerlist = *m_writer.brokerlist;
    m_reader[tid] = bi;
    it = m_reader.find(tid);
  }

  // 如果当前已有拷贝,且状态滞后,则从最新m_writer中拷贝并更新状态
  BrokerListInfo& bi = it->second;
  if (bi.stateid != m_writer.stateid) {
    SSM_METRICS(
        "SYNC CBrokerList from writer to reader,tid:%d state:%d writestate:%d",
        tid, bi.stateid, m_writer.stateid);
    bi.stateid = m_writer.stateid;
    *bi.brokerlist = *m_writer.brokerlist;
  }
  return *bi.brokerlist;
}

CUserAccountInfo::CUserAccountInfo() {
  memset(m_UserAccount, 0, sizeof(m_UserAccount));
  memset(m_UserLoginAccount, 0, sizeof(m_UserLoginAccount));
  memset(m_UserId, 0, sizeof(m_UserId));
  memset(m_Password, 0, sizeof(m_Password));
  memset(m_DisplayName, 0, sizeof(m_DisplayName));
  memset(m_DisplayName_Utf8, 0, sizeof(m_DisplayName_Utf8));
  memset(m_CompanyId, 0, sizeof(m_CompanyId));
  memset(m_CompanyName, 0, sizeof(m_CompanyName));
  memset(m_AccountType, 0, sizeof(m_AccountType));
  memset(m_ExpireDate, 0, sizeof(m_ExpireDate));
  memset(m_Title, 0, sizeof(m_Title));
  memset(m_Telephone, 0, sizeof(m_Telephone));
  memset(m_Mobile, 0, sizeof(m_Mobile));
  memset(m_Rm, 0, sizeof(m_Rm));
  memset(m_Msn, 0, sizeof(m_Msn));
  memset(m_QQ, 0, sizeof(m_QQ));
  memset(m_Address, 0, sizeof(m_Address));
  memset(m_BankName, 0, sizeof(m_BankName));
  memset(m_CSEnglishName, 0, sizeof(m_CSEnglishName));
  memset(m_CSTelephone, 0, sizeof(m_CSTelephone));
  memset(m_CSMobile, 0, sizeof(m_CSMobile));
  memset(m_CSEmail, 0, sizeof(m_CSEmail));
  memset(m_SponsorsName, 0, sizeof(m_SponsorsName));
  memset(m_SponsorsID, 0, sizeof(m_SponsorsID));
  memset(m_Department, 0, sizeof(m_Department));
  memset(m_BussinessType, 0, sizeof(m_BussinessType));
  memset(m_QQEnterprise, 0, sizeof(m_QQEnterprise));
  memset(m_QQEnterprise_Company, 0, sizeof(m_QQEnterprise_Company));
  m_CSAgent = false;
  // FIELDCOPY(m_SponsorsName, "ABCD证券");
}

//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
// 本地配置，原option.ini
class CSSUserWebOption_Imp {
 public:
  CSSUserWebOption_Imp() = default;
  ~CSSUserWebOption_Imp() = default;

 public:
  void AddURL(const char* sKey, const char* sValue) {
    if (nullptr == sKey || sKey[0] == '\0') return;
    if (nullptr == sValue || sValue[0] == '\0') return;
    m_Options[sKey] = sValue;
  };
  const char* LoadURL(const char* sKey) {
    if (nullptr == sKey || sKey[0] == '\0') return nullptr;
    auto it = m_Options.find(sKey);
    if (it == m_Options.end()) return nullptr;
    return it->second.c_str();
  };

  void Load() {
    m_Options.clear();
    char path[MAX_PATH] = {0};
    FMTBUF(path, "%s/config/woptions.json", __GetAppPath().c_str());
    std::ifstream is;
#ifdef WIN32
    is.open(path, std::ios::in | ios::_Nocreate);
#else
    is.open(path, std::ios::in);
#endif
    if (is.fail()) return;

    Json::Value ja;
    Json::Reader rd;
    std::string strKey, strValue;
    if (!rd.parse(is, ja)) return;
    if (!ja.isArray()) return;
    auto it = ja.begin();
    auto ite = ja.end();
    for (int i = 0; it != ite; ++it, ++i) {
      Json::Value jsonObj;
      // if (rd.parse(ja[i], jsonObj))
      {
        strKey = ja[i].begin().key().asString();
        strValue = ja[i][strKey].asString();
        m_Options[strKey] = strValue;
      }
    }
    is.close();
  };
  void Save() {
    Json::Value ja(Json::arrayValue);
    for (auto it = m_Options.begin(); it != m_Options.end(); it++) {
      Json::Value jsonObj;
      jsonObj[it->first.c_str()] = Json::Value(it->second.c_str());
      ja.append(jsonObj);
    }

    char path[MAX_PATH] = {0};
    FMTBUF(path, "%s\\config\\woptions.json", __GetAppPath().c_str());

    std::ofstream os;
    os.open(path);

    Json::StyledStreamWriter wr;
    wr.write(os, ja);

    os.close();
  };

 private:
  std::map<std::string, std::string> m_Options;
};

CSSUserWebOption::CSSUserWebOption() {
  m_pImp = new CSSUserWebOption_Imp;
  Load();
}

CSSUserWebOption::~CSSUserWebOption() {
  if (m_pImp) delete m_pImp;
}

void CSSUserWebOption::AddURL(const char* sKey, const char* sValue) {
  if (nullptr != m_pImp) m_pImp->AddURL(sKey, sValue);
}

const char* CSSUserWebOption::LoadURL(const char* sKey) {
  if (nullptr != m_pImp) return m_pImp->LoadURL(sKey);
  return nullptr;
}

void CSSUserWebOption::Load() {
  if (m_pImp) m_pImp->Load();
}

void CSSUserWebOption::Save() {
  if (m_pImp) m_pImp->Save();
}

//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
// 目录菜单，menu.json
class CQBAppMenu_Imp {
  class CFastLock {
    qb::CriticalSectionWrapper* m_cs;

   public:
    CFastLock() { m_cs = qb::CriticalSectionWrapper::CreateCriticalSection(); }
    ~CFastLock() {
      if (m_cs) delete m_cs;
      m_cs = NULL;
    }
    bool Lock() {
      if (m_cs) m_cs->Enter();
      return true;
    }
    bool UnLock() {
      if (m_cs) m_cs->Leave();
      return true;
    }
    class Scoped {
      CFastLock* mx;

     public:
      Scoped(CFastLock& m) : mx(&m) { mx->Lock(); }
      ~Scoped() { mx->UnLock(); }
    };
  };

 public:
  CQBAppMenu_Imp(const char* sType) : m_sType(sType) { Load(); }
  ~CQBAppMenu_Imp() {}

 public:
  void SetMenu(const char* sMenu, bool bFinished) {
    if (nullptr == sMenu || sMenu[0] == '\0') return;

    CFastLock::Scoped scope(m_lock);
    std::string sm = sMenu;
    if (m_bMenuReceiveComplete)
      m_jsonMenu = sm;
    else
      m_jsonMenu.append(sMenu);

    m_bMenuReceiveComplete = bFinished;

    if (m_bMenuReceiveComplete) {
      Json::Value ja;
      Json::Reader rd;
      if (!rd.parse(m_jsonMenu.c_str(), ja)) {
        Load();
        return;
      }
      Save();
    }
    return;
  }
  int GetMenu(std::string& sMenu) {
    CFastLock::Scoped scoped(m_lock);
    if (!m_bMenuReceiveComplete) return 0;

    sMenu = m_jsonMenu;
    return sMenu.length();
  }

  void Load() {
    CFastLock::Scoped scoped(m_lock);

    m_jsonMenu = "";
    m_bMenuReceiveComplete = true;

    char path[1024] = {0};
    FMTBUF(path, "%s/config/%s.json", __GetAppPath().c_str(), m_sType.c_str());
#ifdef WIN32
    std::ifstream is(path, std::ios::in | ios::_Nocreate);
#else
    std::ifstream is(path, std::ios::in);
#endif
    if (is.fail()) {
      log_warning("[AppMenu] open file failed: \"%s\"", path);
      return;
    }

    std::getline(is, m_jsonMenu, (char)EOF);
    log_debug("[AppMenu] open file success: \"%s\", size = %d", path,
              m_jsonMenu.length());
    is.close();
  }

  void Save() {
    CFastLock::Scoped scoped(m_lock);
    if (!m_bMenuReceiveComplete) return;

    char path[1024] = {0};
    FMTBUF(path, "%s\\config\\%s.json", __GetAppPath().c_str(),
           m_sType.c_str());
    std::ofstream os(path, std::ios::out | std::ios::trunc);
    if (os.fail()) {
      log_warning("[AppMenu] open file failed: \"%s\"", path);
      return;
    }

    os << m_jsonMenu;
    os.close();
  }

 private:
  std::string m_sType;
  std::string m_jsonMenu;
  bool m_bMenuReceiveComplete;
  CFastLock m_lock;
};

CQBAppMenu::CQBAppMenu(const char* sType) {
  m_pImp = new CQBAppMenu_Imp(sType);
}

CQBAppMenu::~CQBAppMenu() {
  if (m_pImp) delete m_pImp;
}

void CQBAppMenu::SetMenu(const char* sMenu, bool bFinished) {
  if (m_pImp) m_pImp->SetMenu(sMenu, bFinished);
}

int CQBAppMenu::GetMenu(std::string& sMenu) {
  if (!m_pImp) return 0;
  return m_pImp->GetMenu(sMenu);
}

void CUserMemberInfo::UpdateMemberInfo(const xUserMemberInfoAck_c* pRawData,
                                       time_t tServerTime) {
  // 此处未考虑分包的情况，需要注意
  if (!pRawData) return;
  m_ListLevel.clear();
  FIELDCOPY(m_UserId, pRawData->m_UserId);
  FIELDCOPY(m_UserAccount, pRawData->m_UserAccount);
  FIELDCOPY(m_CompanyId, pRawData->m_CompanyId);
  if (strcmp(pRawData->m_IsPaidCustom, "1") != 0 &&
      strlen(pRawData->m_MemberLevel) != 0 && strlen(m_MemberLevel) != 0 &&
      strcmp(pRawData->m_MemberLevel, m_MemberLevel) != 0) {
    // m_bLevelChanged = true; //通知前端弹窗
    int levelNew = atoi(pRawData->m_MemberLevel);
    int levelOld = atoi(m_MemberLevel);
    if (levelNew > levelOld)
      m_bLevelChanged = true;
    else
      m_bLevelChanged = false;
  } else {
    m_bLevelChanged = false;
  }
  if (m_bOpenPageNotice) {
    m_bOpenPageGetBp = pRawData->m_CurrentMonthBp - m_CurrentMonthBp;
  } else {
    m_bOpenPageGetBp = 0;  // 通知过后不再更新
  }
  FIELDCOPY(m_MemberLevel, pRawData->m_MemberLevel);
  FIELDCOPY(m_IsPaidCustom, pRawData->m_IsPaidCustom);
  m_CurrentMonthBp = pRawData->m_CurrentMonthBp;
  m_TotalBp = pRawData->m_TotalBp;
  m_OpenPageBpCanGetToday = pRawData->m_OpenPageBpCanGetToday;
  FIELDCOPY(m_FirstLogInReceived, pRawData->m_FirstLogInReceived);
  FIELDCOPY(m_FirstOpenRecommendReceived,
            pRawData->m_FirstOpenRecommendReceived);

  for (auto it : pRawData->m_ListLevel) {  // 浅拷贝注意
    m_ListLevel.push_back(it);
  }

  // 判断是否属于第二天

  qb::base::CTime tNew(tServerTime);
  qb::base::CTime tBefore(m_updateTime);
  qb::base::CTime tToday(tNew.GetYear(), tNew.GetMonth(), tNew.GetDay(), 5, 0,
                         0);
  if (m_updateTime <= 0 || tServerTime <= 0) {
    m_bDayChanged = true;
  } else if (tServerTime >= tToday.GetTime() &&
             tBefore.GetDay() != tNew.GetDay()) {
    m_bDayChanged = true;
  } else {
    m_bDayChanged = false;
  }
  if (strlen(pRawData->m_CompanyId) == 0) {
    m_bDayChanged = true;  // 需要再传登录消息
  }
  m_updateTime = tServerTime;
}

void CUserMobileConfirmInfo::SetParams(const xQBMobileVerifyInfoAck_c* param) {
  if (!param) return;
  m_Initial = true;
  FIELDCOPY(m_mobile, param->m_mobile);
  FIELDCOPY(m_time, param->m_time);
  m_verifyMobile = param->m_verifyMobile;
  m_restTimes = param->m_restTimes;
  m_verifyHour = param->m_verifyHour;
}

bool CUserMobileConfirmInfo::IsInitial() { return m_Initial; }

bool CUserMobileConfirmInfo::NextTime() {
  m_restTimes--;
  return true;
}

CUserMobileConfirmInfo::CUserMobileConfirmInfo() {}

CUserMobileConfirmInfo::~CUserMobileConfirmInfo() {}
